text:
// Warning! This file is autogenerated.
#include <boost/text/bidirectional.hpp>

#include "bidi_tests.hpp"

#include <gtest/gtest.h>

#include <algorithm>

std::vector<int> expected_levels;
std::vector<int> expected_reordered_indices;

TEST(bidi, bidi_377_000)
{

    expected_levels = { 0, 1, -1, 0 };
    expected_reordered_indices = { 0, 1, 3 };

    {
        // FSI AL PDF RLI; 3 ('auto') (line 188501)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x202C, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL PDF RLI; 3 ('LTR') (line 188501)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x202C, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL PDF FSI; 3 ('auto') (line 188502)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x202C, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL PDF FSI; 3 ('LTR') (line 188502)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x202C, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL PDF PDI; 3 ('auto') (line 188503)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x202C, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL PDF PDI; 3 ('LTR') (line 188503)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x202C, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN B; 3 ('auto') (line 188504)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN B; 3 ('LTR') (line 188504)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN S; 3 ('auto') (line 188505)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN S; 3 ('LTR') (line 188505)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN WS; 3 ('auto') (line 188506)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN WS; 3 ('LTR') (line 188506)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN LRI; 3 ('auto') (line 188507)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN LRI; 3 ('LTR') (line 188507)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN RLI; 3 ('auto') (line 188508)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN RLI; 3 ('LTR') (line 188508)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN FSI; 3 ('auto') (line 188509)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN FSI; 3 ('LTR') (line 188509)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN PDI; 3 ('auto') (line 188510)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // FSI AL BN PDI; 3 ('LTR') (line 188510)
        std::vector<uint32_t> const cps = { 0x2068, 0x0608, 0x00AD, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_001)
{

    expected_levels = { 0, 1, -1, 0 };
    expected_reordered_indices = { 0, 1, 3 };

    {
        // PDI R LRE B; 2 ('LTR') (line 188511)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202A, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R LRE S; 2 ('LTR') (line 188512)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202A, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R LRE WS; 2 ('LTR') (line 188513)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202A, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R LRE LRI; 2 ('LTR') (line 188514)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202A, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R LRE RLI; 2 ('LTR') (line 188515)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202A, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R LRE FSI; 2 ('LTR') (line 188516)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202A, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R LRE PDI; 2 ('LTR') (line 188517)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202A, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R LRO B; 2 ('LTR') (line 188518)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202D, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R LRO S; 2 ('LTR') (line 188519)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202D, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R LRO WS; 2 ('LTR') (line 188520)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202D, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_002)
{

    expected_levels = { 0, 1, -1, 0 };
    expected_reordered_indices = { 0, 1, 3 };

    {
        // PDI R LRO LRI; 2 ('LTR') (line 188521)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202D, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R LRO RLI; 2 ('LTR') (line 188522)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202D, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R LRO FSI; 2 ('LTR') (line 188523)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202D, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R LRO PDI; 2 ('LTR') (line 188524)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202D, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R RLE B; 2 ('LTR') (line 188525)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202B, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R RLE S; 2 ('LTR') (line 188526)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202B, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R RLE WS; 2 ('LTR') (line 188527)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202B, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R RLE LRI; 2 ('LTR') (line 188528)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202B, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R RLE RLI; 2 ('LTR') (line 188529)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202B, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R RLE FSI; 2 ('LTR') (line 188530)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202B, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_003)
{

    expected_levels = { 0, 1, -1, 0 };
    expected_reordered_indices = { 0, 1, 3 };

    {
        // PDI R RLE PDI; 2 ('LTR') (line 188531)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202B, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R RLO B; 2 ('LTR') (line 188532)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202E, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R RLO S; 2 ('LTR') (line 188533)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202E, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R RLO WS; 2 ('LTR') (line 188534)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202E, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R RLO LRI; 2 ('LTR') (line 188535)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202E, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R RLO RLI; 2 ('LTR') (line 188536)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202E, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R RLO FSI; 2 ('LTR') (line 188537)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202E, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R RLO PDI; 2 ('LTR') (line 188538)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202E, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R PDF L; 2 ('LTR') (line 188539)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202C, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R PDF ES; 2 ('LTR') (line 188540)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202C, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_004)
{

    expected_levels = { 0, 1, -1, 0 };
    expected_reordered_indices = { 0, 1, 3 };

    {
        // PDI R PDF ET; 2 ('LTR') (line 188541)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202C, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R PDF CS; 2 ('LTR') (line 188542)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202C, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R PDF B; 2 ('LTR') (line 188543)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202C, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R PDF S; 2 ('LTR') (line 188544)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202C, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R PDF WS; 2 ('LTR') (line 188545)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202C, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R PDF ON; 2 ('LTR') (line 188546)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202C, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R PDF LRI; 2 ('LTR') (line 188547)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202C, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R PDF RLI; 2 ('LTR') (line 188548)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202C, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R PDF FSI; 2 ('LTR') (line 188549)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202C, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R PDF PDI; 2 ('LTR') (line 188550)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x202C, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_005)
{

    expected_levels = { 0, 1, -1, 0 };
    expected_reordered_indices = { 0, 1, 3 };

    {
        // PDI R BN L; 2 ('LTR') (line 188551)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x00AD, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R BN ES; 2 ('LTR') (line 188552)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x00AD, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R BN ET; 2 ('LTR') (line 188553)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x00AD, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R BN CS; 2 ('LTR') (line 188554)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x00AD, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R BN B; 2 ('LTR') (line 188555)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x00AD, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R BN S; 2 ('LTR') (line 188556)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x00AD, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R BN WS; 2 ('LTR') (line 188557)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x00AD, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R BN ON; 2 ('LTR') (line 188558)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x00AD, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R BN LRI; 2 ('LTR') (line 188559)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x00AD, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R BN RLI; 2 ('LTR') (line 188560)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x00AD, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_006)
{

    expected_levels = { 0, 1, -1, 0 };
    expected_reordered_indices = { 0, 1, 3 };

    {
        // PDI R BN FSI; 2 ('LTR') (line 188561)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x00AD, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI R BN PDI; 2 ('LTR') (line 188562)
        std::vector<uint32_t> const cps = { 0x2069, 0x05BE, 0x00AD, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL LRE B; 2 ('LTR') (line 188563)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202A, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL LRE S; 2 ('LTR') (line 188564)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202A, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL LRE WS; 2 ('LTR') (line 188565)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202A, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL LRE LRI; 2 ('LTR') (line 188566)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202A, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL LRE RLI; 2 ('LTR') (line 188567)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202A, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL LRE FSI; 2 ('LTR') (line 188568)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202A, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL LRE PDI; 2 ('LTR') (line 188569)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202A, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL LRO B; 2 ('LTR') (line 188570)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202D, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_007)
{

    expected_levels = { 0, 1, -1, 0 };
    expected_reordered_indices = { 0, 1, 3 };

    {
        // PDI AL LRO S; 2 ('LTR') (line 188571)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202D, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL LRO WS; 2 ('LTR') (line 188572)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202D, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL LRO LRI; 2 ('LTR') (line 188573)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202D, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL LRO RLI; 2 ('LTR') (line 188574)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202D, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL LRO FSI; 2 ('LTR') (line 188575)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202D, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL LRO PDI; 2 ('LTR') (line 188576)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202D, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL RLE B; 2 ('LTR') (line 188577)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202B, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL RLE S; 2 ('LTR') (line 188578)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202B, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL RLE WS; 2 ('LTR') (line 188579)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202B, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL RLE LRI; 2 ('LTR') (line 188580)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202B, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_008)
{

    expected_levels = { 0, 1, -1, 0 };
    expected_reordered_indices = { 0, 1, 3 };

    {
        // PDI AL RLE RLI; 2 ('LTR') (line 188581)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202B, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL RLE FSI; 2 ('LTR') (line 188582)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202B, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL RLE PDI; 2 ('LTR') (line 188583)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202B, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL RLO B; 2 ('LTR') (line 188584)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202E, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL RLO S; 2 ('LTR') (line 188585)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202E, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL RLO WS; 2 ('LTR') (line 188586)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202E, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL RLO LRI; 2 ('LTR') (line 188587)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202E, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL RLO RLI; 2 ('LTR') (line 188588)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202E, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL RLO FSI; 2 ('LTR') (line 188589)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202E, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL RLO PDI; 2 ('LTR') (line 188590)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202E, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_009)
{

    expected_levels = { 0, 1, -1, 0 };
    expected_reordered_indices = { 0, 1, 3 };

    {
        // PDI AL PDF L; 2 ('LTR') (line 188591)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202C, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL PDF ES; 2 ('LTR') (line 188592)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202C, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL PDF ET; 2 ('LTR') (line 188593)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202C, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL PDF CS; 2 ('LTR') (line 188594)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202C, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL PDF B; 2 ('LTR') (line 188595)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202C, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL PDF S; 2 ('LTR') (line 188596)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202C, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL PDF WS; 2 ('LTR') (line 188597)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202C, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL PDF ON; 2 ('LTR') (line 188598)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202C, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL PDF LRI; 2 ('LTR') (line 188599)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202C, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL PDF RLI; 2 ('LTR') (line 188600)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202C, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_010)
{

    expected_levels = { 0, 1, -1, 0 };
    expected_reordered_indices = { 0, 1, 3 };

    {
        // PDI AL PDF FSI; 2 ('LTR') (line 188601)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202C, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL PDF PDI; 2 ('LTR') (line 188602)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x202C, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL BN L; 2 ('LTR') (line 188603)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x00AD, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL BN ES; 2 ('LTR') (line 188604)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x00AD, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL BN ET; 2 ('LTR') (line 188605)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x00AD, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL BN CS; 2 ('LTR') (line 188606)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x00AD, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL BN B; 2 ('LTR') (line 188607)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x00AD, 0x2029 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL BN S; 2 ('LTR') (line 188608)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x00AD, 0x0009 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL BN WS; 2 ('LTR') (line 188609)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x00AD, 0x0020 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL BN ON; 2 ('LTR') (line 188610)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x00AD, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_011)
{

    expected_levels = { 0, 1, -1, 0 };
    expected_reordered_indices = { 0, 1, 3 };

    {
        // PDI AL BN LRI; 2 ('LTR') (line 188611)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x00AD, 0x2066 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL BN RLI; 2 ('LTR') (line 188612)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x00AD, 0x2067 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL BN FSI; 2 ('LTR') (line 188613)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x00AD, 0x2068 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // PDI AL BN PDI; 2 ('LTR') (line 188614)
        std::vector<uint32_t> const cps = { 0x2069, 0x0608, 0x00AD, 0x2069 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // L R RLE R; 3 ('auto') (line 188620)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLE R; 3 ('LTR') (line 188620)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLE AL; 3 ('auto') (line 188621)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLE AL; 3 ('LTR') (line 188621)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLE ES; 3 ('auto') (line 188622)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLE ES; 3 ('LTR') (line 188622)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLE ET; 3 ('auto') (line 188623)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLE ET; 3 ('LTR') (line 188623)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLE CS; 3 ('auto') (line 188624)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLE CS; 3 ('LTR') (line 188624)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLE NSM; 3 ('auto') (line 188625)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLE NSM; 3 ('LTR') (line 188625)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_012)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // L R RLE ON; 3 ('auto') (line 188626)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLE ON; 3 ('LTR') (line 188626)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO L; 3 ('auto') (line 188627)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO L; 3 ('LTR') (line 188627)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO R; 3 ('auto') (line 188628)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO R; 3 ('LTR') (line 188628)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO AL; 3 ('auto') (line 188629)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO AL; 3 ('LTR') (line 188629)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO EN; 3 ('auto') (line 188630)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO EN; 3 ('LTR') (line 188630)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO ES; 3 ('auto') (line 188631)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO ES; 3 ('LTR') (line 188631)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO ET; 3 ('auto') (line 188632)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO ET; 3 ('LTR') (line 188632)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO AN; 3 ('auto') (line 188633)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO AN; 3 ('LTR') (line 188633)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO CS; 3 ('auto') (line 188634)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO CS; 3 ('LTR') (line 188634)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO NSM; 3 ('auto') (line 188635)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO NSM; 3 ('LTR') (line 188635)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_013)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // L R RLO ON; 3 ('auto') (line 188636)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R RLO ON; 3 ('LTR') (line 188636)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R PDF R; 3 ('auto') (line 188637)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R PDF R; 3 ('LTR') (line 188637)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R PDF AL; 3 ('auto') (line 188638)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R PDF AL; 3 ('LTR') (line 188638)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R PDF NSM; 3 ('auto') (line 188639)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R PDF NSM; 3 ('LTR') (line 188639)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R BN R; 3 ('auto') (line 188640)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R BN R; 3 ('LTR') (line 188640)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R BN AL; 3 ('auto') (line 188641)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R BN AL; 3 ('LTR') (line 188641)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R BN NSM; 3 ('auto') (line 188642)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L R BN NSM; 3 ('LTR') (line 188642)
        std::vector<uint32_t> const cps = { 0x0041, 0x05BE, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLE R; 3 ('auto') (line 188643)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLE R; 3 ('LTR') (line 188643)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLE AL; 3 ('auto') (line 188644)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLE AL; 3 ('LTR') (line 188644)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLE ES; 3 ('auto') (line 188645)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLE ES; 3 ('LTR') (line 188645)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_014)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // L AL RLE ET; 3 ('auto') (line 188646)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLE ET; 3 ('LTR') (line 188646)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLE CS; 3 ('auto') (line 188647)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLE CS; 3 ('LTR') (line 188647)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLE NSM; 3 ('auto') (line 188648)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLE NSM; 3 ('LTR') (line 188648)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLE ON; 3 ('auto') (line 188649)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLE ON; 3 ('LTR') (line 188649)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO L; 3 ('auto') (line 188650)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO L; 3 ('LTR') (line 188650)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO R; 3 ('auto') (line 188651)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO R; 3 ('LTR') (line 188651)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO AL; 3 ('auto') (line 188652)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO AL; 3 ('LTR') (line 188652)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO EN; 3 ('auto') (line 188653)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO EN; 3 ('LTR') (line 188653)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO ES; 3 ('auto') (line 188654)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO ES; 3 ('LTR') (line 188654)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO ET; 3 ('auto') (line 188655)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO ET; 3 ('LTR') (line 188655)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_015)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // L AL RLO AN; 3 ('auto') (line 188656)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO AN; 3 ('LTR') (line 188656)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO CS; 3 ('auto') (line 188657)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO CS; 3 ('LTR') (line 188657)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO NSM; 3 ('auto') (line 188658)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO NSM; 3 ('LTR') (line 188658)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO ON; 3 ('auto') (line 188659)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL RLO ON; 3 ('LTR') (line 188659)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL PDF R; 3 ('auto') (line 188660)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL PDF R; 3 ('LTR') (line 188660)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL PDF AL; 3 ('auto') (line 188661)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL PDF AL; 3 ('LTR') (line 188661)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL PDF NSM; 3 ('auto') (line 188662)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL PDF NSM; 3 ('LTR') (line 188662)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL BN R; 3 ('auto') (line 188663)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL BN R; 3 ('LTR') (line 188663)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL BN AL; 3 ('auto') (line 188664)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL BN AL; 3 ('LTR') (line 188664)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL BN NSM; 3 ('auto') (line 188665)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), -1);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), -1);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, -1)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // L AL BN NSM; 3 ('LTR') (line 188665)
        std::vector<uint32_t> const cps = { 0x0041, 0x0608, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_016)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // EN R RLE R; 2 ('LTR') (line 188666)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLE AL; 2 ('LTR') (line 188667)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLE ES; 2 ('LTR') (line 188668)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLE ET; 2 ('LTR') (line 188669)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLE CS; 2 ('LTR') (line 188670)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLE NSM; 2 ('LTR') (line 188671)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLE ON; 2 ('LTR') (line 188672)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLO L; 2 ('LTR') (line 188673)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLO R; 2 ('LTR') (line 188674)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLO AL; 2 ('LTR') (line 188675)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_017)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // EN R RLO EN; 2 ('LTR') (line 188676)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLO ES; 2 ('LTR') (line 188677)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLO ET; 2 ('LTR') (line 188678)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLO AN; 2 ('LTR') (line 188679)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLO CS; 2 ('LTR') (line 188680)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLO NSM; 2 ('LTR') (line 188681)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R RLO ON; 2 ('LTR') (line 188682)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R PDF R; 2 ('LTR') (line 188683)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R PDF AL; 2 ('LTR') (line 188684)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R PDF NSM; 2 ('LTR') (line 188685)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_018)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // EN R BN R; 2 ('LTR') (line 188686)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R BN AL; 2 ('LTR') (line 188687)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN R BN NSM; 2 ('LTR') (line 188688)
        std::vector<uint32_t> const cps = { 0x0030, 0x05BE, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLE R; 2 ('LTR') (line 188689)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLE AL; 2 ('LTR') (line 188690)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLE ES; 2 ('LTR') (line 188691)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLE ET; 2 ('LTR') (line 188692)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLE CS; 2 ('LTR') (line 188693)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLE NSM; 2 ('LTR') (line 188694)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLE ON; 2 ('LTR') (line 188695)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_019)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // EN AL RLO L; 2 ('LTR') (line 188696)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLO R; 2 ('LTR') (line 188697)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLO AL; 2 ('LTR') (line 188698)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLO EN; 2 ('LTR') (line 188699)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLO ES; 2 ('LTR') (line 188700)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLO ET; 2 ('LTR') (line 188701)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLO AN; 2 ('LTR') (line 188702)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLO CS; 2 ('LTR') (line 188703)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLO NSM; 2 ('LTR') (line 188704)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL RLO ON; 2 ('LTR') (line 188705)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_020)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // EN AL PDF R; 2 ('LTR') (line 188706)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL PDF AL; 2 ('LTR') (line 188707)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL PDF NSM; 2 ('LTR') (line 188708)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL BN R; 2 ('LTR') (line 188709)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL BN AL; 2 ('LTR') (line 188710)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // EN AL BN NSM; 2 ('LTR') (line 188711)
        std::vector<uint32_t> const cps = { 0x0030, 0x0608, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLE R; 2 ('LTR') (line 188712)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLE AL; 2 ('LTR') (line 188713)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLE ES; 2 ('LTR') (line 188714)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLE ET; 2 ('LTR') (line 188715)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_021)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // ES R RLE CS; 2 ('LTR') (line 188716)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLE NSM; 2 ('LTR') (line 188717)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLE ON; 2 ('LTR') (line 188718)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLO L; 2 ('LTR') (line 188719)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLO R; 2 ('LTR') (line 188720)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLO AL; 2 ('LTR') (line 188721)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLO EN; 2 ('LTR') (line 188722)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLO ES; 2 ('LTR') (line 188723)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLO ET; 2 ('LTR') (line 188724)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLO AN; 2 ('LTR') (line 188725)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_022)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // ES R RLO CS; 2 ('LTR') (line 188726)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLO NSM; 2 ('LTR') (line 188727)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R RLO ON; 2 ('LTR') (line 188728)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R PDF R; 2 ('LTR') (line 188729)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R PDF AL; 2 ('LTR') (line 188730)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R PDF NSM; 2 ('LTR') (line 188731)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R BN R; 2 ('LTR') (line 188732)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R BN AL; 2 ('LTR') (line 188733)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES R BN NSM; 2 ('LTR') (line 188734)
        std::vector<uint32_t> const cps = { 0x002B, 0x05BE, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLE R; 2 ('LTR') (line 188735)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_023)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // ES AL RLE AL; 2 ('LTR') (line 188736)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLE ES; 2 ('LTR') (line 188737)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLE ET; 2 ('LTR') (line 188738)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLE CS; 2 ('LTR') (line 188739)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLE NSM; 2 ('LTR') (line 188740)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLE ON; 2 ('LTR') (line 188741)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLO L; 2 ('LTR') (line 188742)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLO R; 2 ('LTR') (line 188743)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLO AL; 2 ('LTR') (line 188744)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLO EN; 2 ('LTR') (line 188745)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_024)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // ES AL RLO ES; 2 ('LTR') (line 188746)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLO ET; 2 ('LTR') (line 188747)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLO AN; 2 ('LTR') (line 188748)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLO CS; 2 ('LTR') (line 188749)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLO NSM; 2 ('LTR') (line 188750)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL RLO ON; 2 ('LTR') (line 188751)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL PDF R; 2 ('LTR') (line 188752)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL PDF AL; 2 ('LTR') (line 188753)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL PDF NSM; 2 ('LTR') (line 188754)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL BN R; 2 ('LTR') (line 188755)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_025)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // ES AL BN AL; 2 ('LTR') (line 188756)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ES AL BN NSM; 2 ('LTR') (line 188757)
        std::vector<uint32_t> const cps = { 0x002B, 0x0608, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLE R; 2 ('LTR') (line 188758)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLE AL; 2 ('LTR') (line 188759)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLE ES; 2 ('LTR') (line 188760)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLE ET; 2 ('LTR') (line 188761)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLE CS; 2 ('LTR') (line 188762)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLE NSM; 2 ('LTR') (line 188763)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLE ON; 2 ('LTR') (line 188764)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLO L; 2 ('LTR') (line 188765)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_026)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // ET R RLO R; 2 ('LTR') (line 188766)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLO AL; 2 ('LTR') (line 188767)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLO EN; 2 ('LTR') (line 188768)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLO ES; 2 ('LTR') (line 188769)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLO ET; 2 ('LTR') (line 188770)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLO AN; 2 ('LTR') (line 188771)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLO CS; 2 ('LTR') (line 188772)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLO NSM; 2 ('LTR') (line 188773)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R RLO ON; 2 ('LTR') (line 188774)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R PDF R; 2 ('LTR') (line 188775)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_027)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // ET R PDF AL; 2 ('LTR') (line 188776)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R PDF NSM; 2 ('LTR') (line 188777)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R BN R; 2 ('LTR') (line 188778)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R BN AL; 2 ('LTR') (line 188779)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET R BN NSM; 2 ('LTR') (line 188780)
        std::vector<uint32_t> const cps = { 0x0023, 0x05BE, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLE R; 2 ('LTR') (line 188781)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLE AL; 2 ('LTR') (line 188782)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLE ES; 2 ('LTR') (line 188783)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLE ET; 2 ('LTR') (line 188784)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLE CS; 2 ('LTR') (line 188785)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_028)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // ET AL RLE NSM; 2 ('LTR') (line 188786)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLE ON; 2 ('LTR') (line 188787)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLO L; 2 ('LTR') (line 188788)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLO R; 2 ('LTR') (line 188789)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLO AL; 2 ('LTR') (line 188790)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLO EN; 2 ('LTR') (line 188791)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLO ES; 2 ('LTR') (line 188792)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLO ET; 2 ('LTR') (line 188793)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLO AN; 2 ('LTR') (line 188794)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLO CS; 2 ('LTR') (line 188795)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_029)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // ET AL RLO NSM; 2 ('LTR') (line 188796)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL RLO ON; 2 ('LTR') (line 188797)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL PDF R; 2 ('LTR') (line 188798)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL PDF AL; 2 ('LTR') (line 188799)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL PDF NSM; 2 ('LTR') (line 188800)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL BN R; 2 ('LTR') (line 188801)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL BN AL; 2 ('LTR') (line 188802)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ET AL BN NSM; 2 ('LTR') (line 188803)
        std::vector<uint32_t> const cps = { 0x0023, 0x0608, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLE R; 2 ('LTR') (line 188804)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLE AL; 2 ('LTR') (line 188805)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_030)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // CS R RLE ES; 2 ('LTR') (line 188806)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLE ET; 2 ('LTR') (line 188807)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLE CS; 2 ('LTR') (line 188808)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLE NSM; 2 ('LTR') (line 188809)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLE ON; 2 ('LTR') (line 188810)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLO L; 2 ('LTR') (line 188811)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLO R; 2 ('LTR') (line 188812)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLO AL; 2 ('LTR') (line 188813)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLO EN; 2 ('LTR') (line 188814)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLO ES; 2 ('LTR') (line 188815)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_031)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // CS R RLO ET; 2 ('LTR') (line 188816)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLO AN; 2 ('LTR') (line 188817)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLO CS; 2 ('LTR') (line 188818)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLO NSM; 2 ('LTR') (line 188819)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R RLO ON; 2 ('LTR') (line 188820)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R PDF R; 2 ('LTR') (line 188821)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R PDF AL; 2 ('LTR') (line 188822)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R PDF NSM; 2 ('LTR') (line 188823)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R BN R; 2 ('LTR') (line 188824)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS R BN AL; 2 ('LTR') (line 188825)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_032)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // CS R BN NSM; 2 ('LTR') (line 188826)
        std::vector<uint32_t> const cps = { 0x002C, 0x05BE, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLE R; 2 ('LTR') (line 188827)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLE AL; 2 ('LTR') (line 188828)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLE ES; 2 ('LTR') (line 188829)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLE ET; 2 ('LTR') (line 188830)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLE CS; 2 ('LTR') (line 188831)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLE NSM; 2 ('LTR') (line 188832)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLE ON; 2 ('LTR') (line 188833)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLO L; 2 ('LTR') (line 188834)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLO R; 2 ('LTR') (line 188835)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_033)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // CS AL RLO AL; 2 ('LTR') (line 188836)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLO EN; 2 ('LTR') (line 188837)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLO ES; 2 ('LTR') (line 188838)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLO ET; 2 ('LTR') (line 188839)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLO AN; 2 ('LTR') (line 188840)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLO CS; 2 ('LTR') (line 188841)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLO NSM; 2 ('LTR') (line 188842)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL RLO ON; 2 ('LTR') (line 188843)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL PDF R; 2 ('LTR') (line 188844)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL PDF AL; 2 ('LTR') (line 188845)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_034)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // CS AL PDF NSM; 2 ('LTR') (line 188846)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL BN R; 2 ('LTR') (line 188847)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL BN AL; 2 ('LTR') (line 188848)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // CS AL BN NSM; 2 ('LTR') (line 188849)
        std::vector<uint32_t> const cps = { 0x002C, 0x0608, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLE R; 2 ('LTR') (line 188850)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLE AL; 2 ('LTR') (line 188851)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLE ES; 2 ('LTR') (line 188852)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLE ET; 2 ('LTR') (line 188853)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLE CS; 2 ('LTR') (line 188854)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLE NSM; 2 ('LTR') (line 188855)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_035)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // NSM R RLE ON; 2 ('LTR') (line 188856)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLO L; 2 ('LTR') (line 188857)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLO R; 2 ('LTR') (line 188858)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLO AL; 2 ('LTR') (line 188859)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLO EN; 2 ('LTR') (line 188860)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLO ES; 2 ('LTR') (line 188861)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLO ET; 2 ('LTR') (line 188862)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLO AN; 2 ('LTR') (line 188863)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLO CS; 2 ('LTR') (line 188864)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R RLO NSM; 2 ('LTR') (line 188865)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_036)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // NSM R RLO ON; 2 ('LTR') (line 188866)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R PDF R; 2 ('LTR') (line 188867)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R PDF AL; 2 ('LTR') (line 188868)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R PDF NSM; 2 ('LTR') (line 188869)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R BN R; 2 ('LTR') (line 188870)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R BN AL; 2 ('LTR') (line 188871)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM R BN NSM; 2 ('LTR') (line 188872)
        std::vector<uint32_t> const cps = { 0x0300, 0x05BE, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLE R; 2 ('LTR') (line 188873)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLE AL; 2 ('LTR') (line 188874)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLE ES; 2 ('LTR') (line 188875)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_037)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // NSM AL RLE ET; 2 ('LTR') (line 188876)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLE CS; 2 ('LTR') (line 188877)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLE NSM; 2 ('LTR') (line 188878)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLE ON; 2 ('LTR') (line 188879)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLO L; 2 ('LTR') (line 188880)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLO R; 2 ('LTR') (line 188881)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLO AL; 2 ('LTR') (line 188882)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLO EN; 2 ('LTR') (line 188883)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLO ES; 2 ('LTR') (line 188884)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLO ET; 2 ('LTR') (line 188885)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_038)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // NSM AL RLO AN; 2 ('LTR') (line 188886)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLO CS; 2 ('LTR') (line 188887)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLO NSM; 2 ('LTR') (line 188888)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL RLO ON; 2 ('LTR') (line 188889)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL PDF R; 2 ('LTR') (line 188890)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL PDF AL; 2 ('LTR') (line 188891)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL PDF NSM; 2 ('LTR') (line 188892)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL BN R; 2 ('LTR') (line 188893)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL BN AL; 2 ('LTR') (line 188894)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // NSM AL BN NSM; 2 ('LTR') (line 188895)
        std::vector<uint32_t> const cps = { 0x0300, 0x0608, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_039)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // S R RLE R; 2 ('LTR') (line 188896)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLE AL; 2 ('LTR') (line 188897)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLE ES; 2 ('LTR') (line 188898)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLE ET; 2 ('LTR') (line 188899)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLE CS; 2 ('LTR') (line 188900)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLE NSM; 2 ('LTR') (line 188901)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLE ON; 2 ('LTR') (line 188902)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLO L; 2 ('LTR') (line 188903)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLO R; 2 ('LTR') (line 188904)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLO AL; 2 ('LTR') (line 188905)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_040)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // S R RLO EN; 2 ('LTR') (line 188906)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLO ES; 2 ('LTR') (line 188907)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLO ET; 2 ('LTR') (line 188908)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLO AN; 2 ('LTR') (line 188909)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLO CS; 2 ('LTR') (line 188910)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLO NSM; 2 ('LTR') (line 188911)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R RLO ON; 2 ('LTR') (line 188912)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R PDF R; 2 ('LTR') (line 188913)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R PDF AL; 2 ('LTR') (line 188914)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R PDF NSM; 2 ('LTR') (line 188915)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_041)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // S R BN R; 2 ('LTR') (line 188916)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R BN AL; 2 ('LTR') (line 188917)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S R BN NSM; 2 ('LTR') (line 188918)
        std::vector<uint32_t> const cps = { 0x0009, 0x05BE, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLE R; 2 ('LTR') (line 188919)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLE AL; 2 ('LTR') (line 188920)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLE ES; 2 ('LTR') (line 188921)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLE ET; 2 ('LTR') (line 188922)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLE CS; 2 ('LTR') (line 188923)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLE NSM; 2 ('LTR') (line 188924)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLE ON; 2 ('LTR') (line 188925)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_042)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // S AL RLO L; 2 ('LTR') (line 188926)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLO R; 2 ('LTR') (line 188927)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLO AL; 2 ('LTR') (line 188928)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLO EN; 2 ('LTR') (line 188929)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLO ES; 2 ('LTR') (line 188930)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLO ET; 2 ('LTR') (line 188931)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLO AN; 2 ('LTR') (line 188932)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLO CS; 2 ('LTR') (line 188933)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLO NSM; 2 ('LTR') (line 188934)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL RLO ON; 2 ('LTR') (line 188935)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_043)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // S AL PDF R; 2 ('LTR') (line 188936)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL PDF AL; 2 ('LTR') (line 188937)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL PDF NSM; 2 ('LTR') (line 188938)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL BN R; 2 ('LTR') (line 188939)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL BN AL; 2 ('LTR') (line 188940)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // S AL BN NSM; 2 ('LTR') (line 188941)
        std::vector<uint32_t> const cps = { 0x0009, 0x0608, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLE R; 2 ('LTR') (line 188942)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLE AL; 2 ('LTR') (line 188943)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLE ES; 2 ('LTR') (line 188944)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLE ET; 2 ('LTR') (line 188945)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_044)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // WS R RLE CS; 2 ('LTR') (line 188946)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLE NSM; 2 ('LTR') (line 188947)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLE ON; 2 ('LTR') (line 188948)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLO L; 2 ('LTR') (line 188949)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLO R; 2 ('LTR') (line 188950)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLO AL; 2 ('LTR') (line 188951)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLO EN; 2 ('LTR') (line 188952)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLO ES; 2 ('LTR') (line 188953)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLO ET; 2 ('LTR') (line 188954)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLO AN; 2 ('LTR') (line 188955)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_045)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // WS R RLO CS; 2 ('LTR') (line 188956)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLO NSM; 2 ('LTR') (line 188957)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R RLO ON; 2 ('LTR') (line 188958)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R PDF R; 2 ('LTR') (line 188959)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R PDF AL; 2 ('LTR') (line 188960)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R PDF NSM; 2 ('LTR') (line 188961)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R BN R; 2 ('LTR') (line 188962)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R BN AL; 2 ('LTR') (line 188963)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS R BN NSM; 2 ('LTR') (line 188964)
        std::vector<uint32_t> const cps = { 0x0020, 0x05BE, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLE R; 2 ('LTR') (line 188965)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_046)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // WS AL RLE AL; 2 ('LTR') (line 188966)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLE ES; 2 ('LTR') (line 188967)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLE ET; 2 ('LTR') (line 188968)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLE CS; 2 ('LTR') (line 188969)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLE NSM; 2 ('LTR') (line 188970)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLE ON; 2 ('LTR') (line 188971)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLO L; 2 ('LTR') (line 188972)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLO R; 2 ('LTR') (line 188973)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLO AL; 2 ('LTR') (line 188974)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLO EN; 2 ('LTR') (line 188975)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_047)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // WS AL RLO ES; 2 ('LTR') (line 188976)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLO ET; 2 ('LTR') (line 188977)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLO AN; 2 ('LTR') (line 188978)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202E, 0x0660 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLO CS; 2 ('LTR') (line 188979)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202E, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLO NSM; 2 ('LTR') (line 188980)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202E, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL RLO ON; 2 ('LTR') (line 188981)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202E, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL PDF R; 2 ('LTR') (line 188982)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202C, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL PDF AL; 2 ('LTR') (line 188983)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202C, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL PDF NSM; 2 ('LTR') (line 188984)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x202C, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL BN R; 2 ('LTR') (line 188985)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x00AD, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_048)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // WS AL BN AL; 2 ('LTR') (line 188986)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x00AD, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // WS AL BN NSM; 2 ('LTR') (line 188987)
        std::vector<uint32_t> const cps = { 0x0020, 0x0608, 0x00AD, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ON R RLE R; 2 ('LTR') (line 188988)
        std::vector<uint32_t> const cps = { 0x0021, 0x05BE, 0x202B, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ON R RLE AL; 2 ('LTR') (line 188989)
        std::vector<uint32_t> const cps = { 0x0021, 0x05BE, 0x202B, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ON R RLE ES; 2 ('LTR') (line 188990)
        std::vector<uint32_t> const cps = { 0x0021, 0x05BE, 0x202B, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ON R RLE ET; 2 ('LTR') (line 188991)
        std::vector<uint32_t> const cps = { 0x0021, 0x05BE, 0x202B, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ON R RLE CS; 2 ('LTR') (line 188992)
        std::vector<uint32_t> const cps = { 0x0021, 0x05BE, 0x202B, 0x002C };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ON R RLE NSM; 2 ('LTR') (line 188993)
        std::vector<uint32_t> const cps = { 0x0021, 0x05BE, 0x202B, 0x0300 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ON R RLE ON; 2 ('LTR') (line 188994)
        std::vector<uint32_t> const cps = { 0x0021, 0x05BE, 0x202B, 0x0021 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ON R RLO L; 2 ('LTR') (line 188995)
        std::vector<uint32_t> const cps = { 0x0021, 0x05BE, 0x202E, 0x0041 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }
}

TEST(bidi, bidi_377_049)
{

    expected_levels = { 0, 1, -1, 1 };
    expected_reordered_indices = { 0, 3, 1 };

    {
        // ON R RLO R; 2 ('LTR') (line 188996)
        std::vector<uint32_t> const cps = { 0x0021, 0x05BE, 0x202E, 0x05BE };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ON R RLO AL; 2 ('LTR') (line 188997)
        std::vector<uint32_t> const cps = { 0x0021, 0x05BE, 0x202E, 0x0608 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ON R RLO EN; 2 ('LTR') (line 188998)
        std::vector<uint32_t> const cps = { 0x0021, 0x05BE, 0x202E, 0x0030 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ON R RLO ES; 2 ('LTR') (line 188999)
        std::vector<uint32_t> const cps = { 0x0021, 0x05BE, 0x202E, 0x002B };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

    {
        // ON R RLO ET; 2 ('LTR') (line 189000)
        std::vector<uint32_t> const cps = { 0x0021, 0x05BE, 0x202E, 0x0023 };
        std::vector<int> const levels =
            bidi_levels(cps.begin(), cps.end(), 0);
        int i = 0;
        for (int l : expected_levels) {
            if (0 <= l) {
                EXPECT_EQ(levels[i], l) << "i=" << i;
                ++i;
            }
        }
        EXPECT_EQ((int)levels.size(), i);

        std::vector<int> const reordered =
            bidi_reordered_indices(cps.begin(), cps.end(), 0);
        i = 0;
        for (int idx : expected_reordered_indices) {
            // Skip FSI, LRI, RLI, and PDI.
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }

        std::vector<int> reordered_2;
        for (auto subrange :
            boost::text::bidirectional_subranges(cps, 0)) {
            for (auto cp : subrange) {
                reordered_2.push_back(cp);
            }
        }
        i = 0;
        for (int idx : expected_reordered_indices) {
            if (cps[idx] < 0x2066 || 0x2069 < cps[idx]) {
                EXPECT_EQ(reordered_2[i], cps[idx])
                    << std::hex
                    << " 0x" << reordered_2[i]
                    << " 0x" << cps[idx]
                    << std::dec << " i=" << i;
            }
            ++i;
        }
        EXPECT_EQ(i, (int)reordered_2.size());
    }

}

max_stars_repo_name: eightysquirrels/text

max_issues_repo_name: eightysquirrels/text

max_forks_repo_name: eightysquirrels/text