12#include "ns3/assert.h" 
   13#include "ns3/wifi-ru.h" 
  154     { {{-500, -259}, {-253, -12}},
 
  155       {{12, 253}, {259, 500}}}},
 
  293     { {{-1012, -771}, {-765, -524}},
 
  294       {{-500, -259}, {-253, -12}},
 
  295       {{12, 253}, {259, 500}},
 
  296       {{524, 765}, {771, 1012}}}},
 
  298     { {{-1012, -515}, {-509, -12}},
 
  299       {{12, 509}, {515, 1012}}}},
 
  301     { {{-1012, -515}, {-509, -12}, {12, 509}, {515, 1012}}}},
 
  568     { {{-2036, -1795}, {-1789, -1548}},
 
  569       {{-1524, -1283}, {-1277, -1036}},
 
  570       {{-1012, -771}, {-765, -524}},
 
  571       {{-500, -259}, {-253, -12}},
 
  572       {{12, 253}, {259, 500}},
 
  573       {{524, 765}, {771, 1012}},
 
  574       {{1036, 1277}, {1283, 1524}},
 
  575       {{1548, 1789}, {1795, 2036}}}},
 
  577     { {{-2036, -1539}, {-1533, -1036}},
 
  578       {{-1012, -515}, {-509, -12}},
 
  579       {{12, 509}, {515, 1012}},
 
  580       {{1036, 1533}, {1539, 2036}}}},
 
  582     { {{-2036, -1539}, {-1533, -1036}, {-1012, -515}, {-509, -12}},
 
  583       {{12, 509}, {515, 1012}, {1036, 1533}, {1539, 2036}}}},
 
  797std::vector<EhtRu::RuSpec>
 
  800    std::optional<std::size_t> idx;
 
  801    if ((ruAllocation <= 25) || (ruAllocation == 48))
 
  805    else if ((ruAllocation >= 26) && (ruAllocation <= 31))
 
  809    else if (((ruAllocation >= 64) && (ruAllocation <= 95)))
 
  811        idx = ruAllocation & 0x1F8;
 
  817    return idx.has_value() ? 
m_ruAllocations.at(idx.value()) : std::vector<EhtRu::RuSpec>{};
 
 
  828        return isOdd ? 15 : 24;
 
  831        return isOdd ? 25 : 48;
 
  833        return hasUsers ? 64 : 28;
 
  835        return hasUsers ? 72 : 29;
 
  838        return hasUsers ? ruAlloc : 30;
 
 
  845                      bool primary80MHzOrLower80MHz)
 
  848      m_primary160MHz{primary160MHz},
 
  849      m_primary80MHzOrLower80MHz{primary80MHzOrLower80MHz}
 
 
  872    return m_primary160MHz;
 
 
  879    return m_primary80MHzOrLower80MHz;
 
 
  885    auto phyIndex{m_index};
 
  886    const auto primary160IsLower160 = (p20Index < (
MHz_u{320} / 
MHz_u{20}) / 2);
 
  888        ((primary160IsLower160 && !m_primary160MHz) || (!primary160IsLower160 && m_primary160MHz)))
 
  892    const auto indicesPer80MHz = 
GetNRus(
MHz_u{80}, m_ruType, 
true);
 
  894        ((primary160IsLower160 && !m_primary160MHz) || (!primary160IsLower160 && m_primary160MHz)))
 
  896        phyIndex += 2 * indicesPer80MHz;
 
  898    const uint8_t num20MHzSubchannelsIn160 = 
MHz_u{160} / 
MHz_u{20};
 
  899    const auto primary80IsLower80 =
 
  900        ((p20Index % num20MHzSubchannelsIn160) < (num20MHzSubchannelsIn160 / 2));
 
  902        ((m_primary160MHz && ((primary80IsLower80 && !m_primary80MHzOrLower80MHz) ||
 
  903                              (!primary80IsLower80 && m_primary80MHzOrLower80MHz))) ||
 
  904         (!m_primary160MHz && !m_primary80MHzOrLower80MHz)))
 
  906        phyIndex += indicesPer80MHz;
 
 
  914    const auto nRus = 
GetNRus(bw, ruType);
 
  916    const auto indicesPer80MHz = (ruWidth <= 
MHz_u{80}) ? 
GetNRus(
MHz_u{80}, ruType, 
true) : 1;
 
  917    const auto undefinedRusPer80MHz =
 
  919    const auto primary160IsLower160 = (p20Index < (
MHz_u{320} / 
MHz_u{20}) / 2);
 
  920    const auto primary160 =
 
  922         (primary160IsLower160 && phyIndex <= (nRus / 2) + (2 * undefinedRusPer80MHz)) ||
 
  923         (!primary160IsLower160 && phyIndex > (nRus / 2) + (2 * undefinedRusPer80MHz)));
 
  924    bool primary80OrLow80;
 
  927        const uint8_t num20MHzSubchannelsIn160 = 
MHz_u{160} / 
MHz_u{20};
 
  928        const auto primary80IsLower80 =
 
  929            ((p20Index % num20MHzSubchannelsIn160) < (num20MHzSubchannelsIn160 / 2));
 
  930        const auto threshold =
 
  931            ((bw < 
MHz_u{320}) || primary160IsLower160) ? indicesPer80MHz : 3 * indicesPer80MHz;
 
  933                           (primary80IsLower80 && phyIndex <= threshold) ||
 
  934                           (!primary80IsLower80 && phyIndex > threshold);
 
  939                           ((((phyIndex - 1) / indicesPer80MHz) % 2) == 0);
 
  941    return {primary160, primary80OrLow80};
 
 
  952    if (
const auto indicesPer80MHz = 
GetNRus(
MHz_u{80}, ruType, 
true);
 
  953        bw > 
MHz_u{80} && phyIndex > indicesPer80MHz)
 
  955        return (((phyIndex - 1) % indicesPer80MHz) + 1);
 
 
  975    auto nRus = it->second.size();
 
  976    if (!includeUndefinedRus)
 
  978        const auto num80MHz = std::max<uint16_t>(bw / 
MHz_u{80}, 1);
 
  979        const auto undefinedRus =
 
  981        nRus -= undefinedRus;
 
 
  986std::vector<EhtRu::RuSpec>
 
  996        return {{ruType, 1, 
true, 
true}};
 
 1002        return {{ruType, 1, 
true, 
true}, {ruType, 1, 
false, 
true}};
 
 1005    std::vector<EhtRu::RuSpec> ret;
 
 1007    const auto indices = 
GetNRus(std::min(bw, 
MHz_u{80}), ruType, 
true);
 
 1008    for (uint8_t idx80MHz = 0; idx80MHz < (bw / 
MHz_u{80}); ++idx80MHz)
 
 1010        const auto p160 = (idx80MHz < 2);
 
 1011        const auto p80orLow80 = ((idx80MHz % 2) == 0);
 
 1012        for (std::size_t ruIndex = 1; ruIndex <= indices; ++ruIndex)
 
 1014            if (subcarrierGroup.at(ruIndex - 1).empty())
 
 1019            ret.emplace_back(ruType, ruIndex, p160, p80orLow80);
 
 
 1025std::vector<EhtRu::RuSpec>
 
 1033    std::vector<std::size_t> indices;
 
 1034    if (bw >= 
MHz_u{20})
 
 1036        indices.push_back(5);
 
 1038    if (bw >= 
MHz_u{40})
 
 1040        indices.push_back(14);
 
 1042    if (bw >= 
MHz_u{80})
 
 1044        indices.insert(indices.end(), {24, 33});
 
 1047    std::vector<EhtRu::RuSpec> ret;
 
 1048    for (uint8_t idx80MHz = 0; idx80MHz < (bw / 
MHz_u{80}); ++idx80MHz)
 
 1050        const auto p160 = (idx80MHz < 2);
 
 1051        const auto p80orLow80 = ((idx80MHz % 2) == 0);
 
 1052        std::transform(indices.cbegin(),
 
 1054                       std::back_inserter(ret),
 
 1055                       [p160, p80orLow80](
const auto indice) {
 
 1056                           return EhtRu::RuSpec{RuType::RU_26_TONE, indice, p160, p80orLow80};
 
 
 1067    return it->second.at(phyIndex - 1);
 
 
 1098            (ruBw <= 
MHz_u{80}) && (otherRuBw <= 
MHz_u{80}) &&
 
 1104        for (
const auto& rangeRu : rangesRu)
 
 1107            for (
auto& rangeP : rangesP)
 
 1109                if (rangeP.second >= rangeRu.first && rangeRu.second >= rangeP.first)
 
 
 1123    for (uint8_t idx80MHz = 0; idx80MHz < (bw / 
MHz_u{80}); ++idx80MHz)
 
 1125        const auto p160 = (idx80MHz < 2);
 
 1126        const auto p80orLow80 = ((idx80MHz % 2) == 0);
 
 1127        for (std::size_t index = 1; index <= numRus; ++index)
 
 1129            EhtRu::RuSpec searchedRu(searchedRuType, index, p160, p80orLow80);
 
 1136    NS_ABORT_MSG(
"The searched RU type " << searchedRuType << 
" was not found for bw=" << bw
 
 1137                                         << 
" and referenceRu=" << referenceRu);
 
 
 1143                                   std::size_t& nStations,
 
 1144                                   std::size_t& nCentral26TonesRus)
 
 1161        ruType = 
static_cast<RuType>(i);
 
 1164    nStations = 
GetNRus(bandwidth, ruType);
 
 
 1173               ? (bandwidth / 
MHz_u{20})
 
 
 1190    return !(*
this == other);
 
 
 1199    return std::tie(m_ruType, m_index, m_primary160MHz, m_primary80MHzOrLower80MHz) <
 
 1200           std::tie(other.
m_ruType, other.
m_index, m_primary160MHz, m_primary80MHzOrLower80MHz);
 
 
bool m_primary160MHz
true if the RU is allocated in the primary 160MHz channel
std::size_t m_index
RU index (starting at 1) within the 80 MHz segment.
bool operator!=(const RuSpec &other) const
Compare this RU to the given RU.
bool GetPrimary80MHzOrLower80MHz() const
bool operator==(const RuSpec &other) const
Compare this RU to the given RU.
bool m_primary80MHzOrLower80MHz
if the RU is allocated in the primary 160MHz channel, true if the RU is allocated in the primary 80MH...
bool operator<(const RuSpec &other) const
Compare this RU to the given RU.
RuSpec()=default
Default constructor.
RuType GetRuType() const
Get the RU type.
std::size_t GetPhyIndex(MHz_u bw, uint8_t p20Index) const
Get the RU PHY index.
std::size_t GetIndex() const
Get the RU index within the 80 MHz segment.
bool GetPrimary160MHz() const
Get whether the RU is allocated in the primary 160MHz channel.
static const RuAllocationMap m_ruAllocations
Table 36-34 of IEEE802.11be-D7.0.
static bool DoesOverlap(MHz_u bw, RuSpec ru, const std::vector< RuSpec > &v)
Check whether the given RU overlaps with the given set of RUs.
static std::pair< bool, bool > GetPrimaryFlags(MHz_u bw, RuType ruType, std::size_t phyIndex, uint8_t p20Index)
Get the primary flags of a given RU transmitted in a PPDU.
static uint16_t GetEqualizedRuAllocation(RuType ruType, bool isOdd, bool hasUsers)
Get the RU_ALLOCATION value for equal size RUs.
std::map< uint8_t, std::vector< RuSpec > > RuAllocationMap
RU allocation map.
static std::vector< RuSpec > GetRusOfType(MHz_u bw, RuType ruType)
Get the set of distinct RUs of the given type (number of tones) available in an PPDU of the given ban...
static std::vector< RuSpec > GetRuSpecs(uint16_t ruAllocation)
Get the RU specs based on RU_ALLOCATION.
static std::size_t GetIndexIn80MHzSegment(MHz_u bw, RuType ruType, std::size_t phyIndex)
Get the index of a given RU transmitted in a PPDU within its 80 MHz segment.
static SubcarrierGroup GetSubcarrierGroup(MHz_u bw, RuType ruType, std::size_t phyIndex)
Get the subcarrier group of the RU having the given PHY index among all the RUs of the given type (nu...
static std::vector< RuSpec > GetCentral26TonesRus(MHz_u bw, RuType ruType)
Get the set of 26-tone RUs that can be additionally allocated if the given bandwidth is split in RUs ...
static RuSpec FindOverlappingRu(MHz_u bw, RuSpec referenceRu, RuType searchedRuType)
Find the RU allocation of the given RU type overlapping the given reference RU allocation.
static const SubcarrierGroups m_ruSubcarrierGroups
Subcarrier groups for all EHT RUs.
static uint8_t GetNumCentral26TonesRus(MHz_u bw, RuType ruType)
Get the number of 26-tone RUs that can be allocated if returned RU size is greater than 26 tones.
static RuType GetEqualSizedRusForStations(MHz_u bandwidth, std::size_t &nStations, std::size_t &nCentral26TonesRus)
Given the channel bandwidth and the number of stations candidate for being assigned an RU,...
static std::size_t GetNRus(MHz_u bw, RuType ruType, bool includeUndefinedRus=false)
Get the number of distinct RUs of the given type (number of tones) available in a PPDU of the given b...
static MHz_u GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
RuType
The different Resource Unit (RU) types.
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
std::map< BwTonesPair, std::vector< SubcarrierGroup > > SubcarrierGroups
map (bandwidth, number of tones) pairs to the group of subcarrier ranges
double MHz_u
MHz weak type.