2026-07-19 08:34:18 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Main.mqh |
|
|
|
|
|
//| Copyright 2026, Niquel Mendoza. |
|
|
|
|
|
//| https://www.mql5.com/ |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#property copyright "Copyright 2026, Niquel Mendoza."
|
|
|
|
|
#property link "https://www.mql5.com/"
|
|
|
|
|
#property strict
|
|
|
|
|
|
2026-07-21 11:09:28 -05:00
|
|
|
#ifndef FASTCOLLECTIONSBYLEO_COLHASH_HASHBASES_MAIN_MQH
|
|
|
|
|
#define FASTCOLLECTIONSBYLEO_COLHASH_HASHBASES_MAIN_MQH
|
2026-07-19 08:34:18 -05:00
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#include "Def.mqh"
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| TPar requiere al menos: TKey key; ulong hash; |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
namespace TSN
|
|
|
|
|
{
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename TPar, typename TKey, typename TBase>
|
|
|
|
|
class CFastHashTableBase
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
TPar m_table[];
|
|
|
|
|
//int m_table_capacity;
|
|
|
|
|
ulong m_meta[];
|
|
|
|
|
int m_num_groups;
|
2026-07-19 10:13:55 -05:00
|
|
|
uint m_last_created_pos;
|
2026-07-19 08:34:18 -05:00
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
int m_count;
|
|
|
|
|
int m_next_resize;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
int CalcNumGroups(int min_slots) const;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
CFastHashTableBase(void) {}
|
|
|
|
|
~CFastHashTableBase(void) {}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
bool Remove(const TKey& key);
|
2026-07-19 22:56:49 -05:00
|
|
|
void Remove(uint i, int bit_pos);
|
2026-07-19 08:34:18 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
int GetKeys(TKey& keys[]) const;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
__forceinline int Count() const { return m_count; }
|
|
|
|
|
__forceinline bool Contains(const TKey& key) const { return Find(key) != -1; }
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
void Clear();
|
|
|
|
|
void Reserve(int reserve_elements);
|
|
|
|
|
void Init(int new_el_size);
|
|
|
|
|
|
2026-07-19 10:13:55 -05:00
|
|
|
//---
|
|
|
|
|
bool Find(const TKey& key, uint& i, int& bit_pos) const;
|
|
|
|
|
int Find(const TKey& key) const;
|
2026-07-21 10:59:01 -05:00
|
|
|
int Find(const ulong hash) const;
|
2026-07-19 08:34:18 -05:00
|
|
|
|
2026-07-19 10:13:55 -05:00
|
|
|
//---
|
|
|
|
|
bool Add(const TKey& key);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename TPar, typename TKey, typename TBase>
|
|
|
|
|
bool CFastHashTableBase::Add(const TKey& key)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
if(m_count > m_next_resize)
|
|
|
|
|
{
|
|
|
|
|
Reserve((m_num_groups << 3) << 1); // primero convetirmos a "slots".. y a eso lo duplicmos..
|
|
|
|
|
// si teniamos en total 128 slots... lo doubplcas a 256
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const ulong hash = TBase::Hash(key);
|
|
|
|
|
const uint group_f = m_num_groups - 1;
|
|
|
|
|
uint i = uint(hash & group_f); // inicio
|
|
|
|
|
const uchar h2 = uchar(hash >> 57);
|
|
|
|
|
const ulong mask_hashes_finals = h2 * 0x0101010101010101; // mascara
|
|
|
|
|
|
|
|
|
|
//--- Iteracion circular
|
|
|
|
|
int final_pos = -1;
|
|
|
|
|
for(int it = 0; it < m_num_groups; it++)
|
|
|
|
|
{
|
|
|
|
|
//--- Verfiicar si coincide aqui..
|
|
|
|
|
const ulong has_mask_hash = m_meta[i] ^ mask_hashes_finals;
|
|
|
|
|
ulong mask_hash = TSNTABLES_SWAR_HAS(has_mask_hash);
|
|
|
|
|
while(mask_hash != 0)
|
|
|
|
|
{
|
|
|
|
|
const ulong flag = TSNTABLES_SWAR_64_DEJAR_SOLO_MINUS_SIG_BYTE(mask_hash);
|
|
|
|
|
const int pos = TSNTABLES_SWAR_64_GET_BYTE(flag); // nota usamos byte.. posicion exacta
|
|
|
|
|
#ifndef TSN_MQLARTICLES_USE_KEY
|
|
|
|
|
if(m_table[(i << 3) + pos].hash == hash)
|
|
|
|
|
{
|
|
|
|
|
// Ya existe
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
#else // TSN_MQLARTICLES_USE_KEY
|
|
|
|
|
if(TBase::Eq(m_table[(i << 3) + pos].key, key))
|
|
|
|
|
{
|
|
|
|
|
// Ya existe
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
#endif // TSN_MQLARTICLES_USE_KEY
|
|
|
|
|
|
|
|
|
|
mask_hash &= (mask_hash - 1);
|
|
|
|
|
}
|
|
|
|
|
// No existe ahi..
|
|
|
|
|
//---
|
|
|
|
|
const ulong has_mask_emptry = m_meta[i] ^ MQLARTICLES_HASHMAP_MASK_EMPTY;
|
|
|
|
|
const ulong mask_hash_empty = TSNTABLES_SWAR_HAS(has_mask_emptry);
|
|
|
|
|
if(mask_hash_empty != 0)
|
|
|
|
|
{
|
|
|
|
|
const ulong flag = TSNTABLES_SWAR_64_DEJAR_SOLO_MINUS_SIG_BYTE(mask_hash_empty);
|
|
|
|
|
final_pos = TSNTABLES_SWAR_64_GET_BIT(flag); // bit posicion
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
i = (i + 1) & group_f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(final_pos == -1)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// 0 1 2 3 4 5 6 7
|
|
|
|
|
final_pos -= 7;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// final pos en rango de [0-63]
|
|
|
|
|
const ulong clear_mask = ~(255ULL << final_pos);
|
|
|
|
|
m_meta[i] = (m_meta[i] & clear_mask) | (ulong(h2) << final_pos);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_last_created_pos = (i << 3) + (final_pos >> 3); // le añadimos la posicion exacta...
|
|
|
|
|
m_table[m_last_created_pos].key = key;
|
|
|
|
|
m_table[m_last_created_pos].hash = hash;
|
|
|
|
|
m_count++;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2026-07-19 08:34:18 -05:00
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename TPar, typename TKey, typename TBase>
|
|
|
|
|
int CFastHashTableBase::CalcNumGroups(int min_slots) const
|
|
|
|
|
{
|
|
|
|
|
// Cuántos grupos de 8 necesito como mínimo para cubrir min_slots
|
|
|
|
|
int min_groups = (min_slots + 7) >> 3; // redondeo hacia arriba, división por 8
|
|
|
|
|
if(min_groups < 1)
|
|
|
|
|
min_groups = 1;
|
|
|
|
|
|
|
|
|
|
// Redondear hacia arriba a la potencia de 2 más cercana
|
|
|
|
|
int groups = 1;
|
|
|
|
|
while(groups < min_groups)
|
|
|
|
|
groups <<= 1;
|
|
|
|
|
|
|
|
|
|
return groups;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename TPar, typename TKey, typename TBase>
|
|
|
|
|
void CFastHashTableBase::Init(int new_el_size)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
m_num_groups = CalcNumGroups(new_el_size);
|
|
|
|
|
const int total_slots = m_num_groups << 3;
|
|
|
|
|
ArrayResize(m_meta, m_num_groups);
|
|
|
|
|
ArrayResize(m_table, total_slots);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
for(int g = 0; g < m_num_groups; g++)
|
|
|
|
|
m_meta[g] = MQLARTICLES_HASHMAP_MASK_EMPTY;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_count = 0;
|
|
|
|
|
m_next_resize = (total_slots * 7) >> 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename TPar, typename TKey, typename TBase>
|
|
|
|
|
void CFastHashTableBase::Clear(void)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
for(int g = 0; g < m_num_groups; g++)
|
|
|
|
|
m_meta[g] = MQLARTICLES_HASHMAP_MASK_EMPTY;
|
|
|
|
|
|
|
|
|
|
m_count = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename TPar, typename TKey, typename TBase>
|
|
|
|
|
void CFastHashTableBase::Reserve(int reserve_elements)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
// Si la tabla está vacía, es exactamente Init
|
|
|
|
|
if(m_count == 0)
|
|
|
|
|
{
|
|
|
|
|
Init(reserve_elements);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Si ya hay datos, guardamos referencia a la tabla vieja (completa)
|
|
|
|
|
TPar old_table[];
|
|
|
|
|
ulong old_meta[];
|
|
|
|
|
const int old_num_groups = m_num_groups;
|
|
|
|
|
const int prev_table_size = old_num_groups << 3;
|
|
|
|
|
|
|
|
|
|
//--- copy
|
|
|
|
|
ArrayResize(old_table, prev_table_size);
|
|
|
|
|
for(int i = 0; i < prev_table_size; i++)
|
|
|
|
|
old_table[i] = m_table[i];
|
|
|
|
|
|
|
|
|
|
ArrayCopy(old_meta, m_meta);
|
|
|
|
|
|
|
|
|
|
//--- Iniciamos mas grande... tamaño actual + nuevos elementos
|
|
|
|
|
Init(prev_table_size + reserve_elements);
|
|
|
|
|
|
|
|
|
|
//--- Reinsertamos cada elemento válido de la tabla vieja, sin recalcular el hash
|
|
|
|
|
//--- y sin pasar por Add (nunca hay duplicados, ya vienen de una tabla válida)
|
|
|
|
|
const uint group_f = uint(m_num_groups - 1);
|
|
|
|
|
|
|
|
|
|
for(int g = 0; g < old_num_groups; g++)
|
|
|
|
|
{
|
|
|
|
|
ulong occupied_mask = (old_meta[g] & MQLARTICLES_HASHMAP_MASK_HIGH_BIT) ^ MQLARTICLES_HASHMAP_MASK_HIGH_BIT;
|
|
|
|
|
while(occupied_mask != 0)
|
|
|
|
|
{
|
|
|
|
|
const ulong flag = TSNTABLES_SWAR_64_DEJAR_SOLO_MINUS_SIG_BYTE(occupied_mask);
|
|
|
|
|
const int slot = (g << 3) + TSNTABLES_SWAR_64_GET_BYTE(flag);
|
|
|
|
|
const ulong hash = old_table[slot].hash;
|
|
|
|
|
const uchar h2 = uchar(hash >> 57);
|
|
|
|
|
uint i = uint(hash & group_f);
|
|
|
|
|
|
|
|
|
|
//--- buscamos el primer slot vacío
|
|
|
|
|
int final_pos = -1;
|
|
|
|
|
for(int it = 0; it < m_num_groups; it++)
|
|
|
|
|
{
|
|
|
|
|
const ulong has_mask_empty = m_meta[i] ^ MQLARTICLES_HASHMAP_MASK_EMPTY;
|
|
|
|
|
const ulong mask_hash_empty = TSNTABLES_SWAR_HAS(has_mask_empty);
|
|
|
|
|
if(mask_hash_empty != 0)
|
|
|
|
|
{
|
|
|
|
|
const ulong f = TSNTABLES_SWAR_64_DEJAR_SOLO_MINUS_SIG_BYTE(mask_hash_empty);
|
|
|
|
|
final_pos = TSNTABLES_SWAR_64_GET_BIT(f);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
i = (i + 1) & group_f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
final_pos -= 7;
|
|
|
|
|
const ulong clear_mask = ~(255ULL << final_pos);
|
|
|
|
|
m_meta[i] = (m_meta[i] & clear_mask) | (ulong(h2) << final_pos);
|
|
|
|
|
|
|
|
|
|
const uint fpos = (i << 3) + (final_pos >> 3);
|
|
|
|
|
m_table[fpos] = old_table[slot];
|
|
|
|
|
m_count++;
|
|
|
|
|
|
|
|
|
|
occupied_mask &= (occupied_mask - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename TPar, typename TKey, typename TBase>
|
|
|
|
|
int CFastHashTableBase::GetKeys(TKey& keys[]) const
|
|
|
|
|
{
|
|
|
|
|
ArrayResize(keys, m_count);
|
|
|
|
|
int out_idx = 0;
|
|
|
|
|
|
|
|
|
|
for(int group = 0; group < m_num_groups; group++)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
ulong occupied_mask = (m_meta[group] & MQLARTICLES_HASHMAP_MASK_HIGH_BIT) ^ MQLARTICLES_HASHMAP_MASK_HIGH_BIT;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
while(occupied_mask != 0)
|
|
|
|
|
{
|
|
|
|
|
const ulong flag = TSNTABLES_SWAR_64_DEJAR_SOLO_MINUS_SIG_BYTE(occupied_mask);
|
|
|
|
|
const int slot = (group << 3) + TSNTABLES_SWAR_64_GET_BYTE(flag);
|
|
|
|
|
keys[out_idx] = m_table[slot].key;
|
|
|
|
|
out_idx++;
|
|
|
|
|
occupied_mask &= (occupied_mask - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
return out_idx; // debería ser == m_count al final
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename TPar, typename TKey, typename TBase>
|
|
|
|
|
bool CFastHashTableBase::Remove(const TKey& key)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
uint i; // grupo exacto
|
|
|
|
|
int bit_pos; // 0-63
|
|
|
|
|
if(!Find(key, i, bit_pos))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
bit_pos -= 7;
|
|
|
|
|
|
|
|
|
|
const ulong clear_mask = ~(255ULL << bit_pos);
|
|
|
|
|
m_meta[i] = (m_meta[i] & clear_mask) | (MQLARTICLES_HASHMAP_MDEL << bit_pos); // 0xFE = kDeleted
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_count--;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-19 22:56:49 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#define TSN_FASTHASHMAP_INDEX(i, bit_pos) ((i << 3) + (bit_pos >> 3))
|
|
|
|
|
template <typename TPar, typename TKey, typename TBase>
|
|
|
|
|
void CFastHashTableBase::Remove(uint i, int bit_pos)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
bit_pos -= 7;
|
|
|
|
|
const ulong clear_mask = ~(255ULL << bit_pos);
|
|
|
|
|
m_meta[i] = (m_meta[i] & clear_mask) | (MQLARTICLES_HASHMAP_MDEL << bit_pos); // 0xFE = kDeleted
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_count--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2026-07-19 08:34:18 -05:00
|
|
|
//+------------------------------------------------------------------+
|
2026-07-21 10:59:01 -05:00
|
|
|
//| Find |
|
2026-07-19 08:34:18 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename TPar, typename TKey, typename TBase>
|
|
|
|
|
bool CFastHashTableBase::Find(const TKey& key, uint& i, int& bit_pos) const
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
const ulong hash = TBase::Hash(key);
|
|
|
|
|
const uint group_f = m_num_groups - 1;
|
|
|
|
|
i = uint(hash & group_f); // inicio
|
|
|
|
|
const uchar h2 = uchar(hash >> 57);
|
|
|
|
|
const ulong mask_hashes_finals = h2 * 0x0101010101010101; // mascara
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
for(int it = 0; it < m_num_groups; it++)
|
|
|
|
|
{
|
|
|
|
|
//--- Verfiicar si coincide aqui..
|
|
|
|
|
const ulong has_mask_hash = m_meta[i] ^ mask_hashes_finals;
|
|
|
|
|
ulong mask_hash = TSNTABLES_SWAR_HAS(has_mask_hash);
|
|
|
|
|
while(mask_hash != 0)
|
|
|
|
|
{
|
|
|
|
|
const ulong flag = TSNTABLES_SWAR_64_DEJAR_SOLO_MINUS_SIG_BYTE(mask_hash);
|
|
|
|
|
bit_pos = TSNTABLES_SWAR_64_GET_BIT(flag); // nota usamos byte.. posicion exacta
|
|
|
|
|
#ifndef TSN_MQLARTICLES_USE_KEY
|
|
|
|
|
if(m_table[(i << 3) + (bit_pos >> 3)].hash == hash)
|
|
|
|
|
return true;
|
|
|
|
|
#else // TSN_MQLARTICLES_USE_KEY
|
|
|
|
|
if(TBase::Eq(m_table[(i << 3) + (bit_pos >> 3)].key, key))
|
|
|
|
|
return true;
|
|
|
|
|
#endif // TSN_MQLARTICLES_USE_KEY
|
|
|
|
|
|
|
|
|
|
mask_hash &= (mask_hash - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const ulong has_mask_emptry = m_meta[i] ^ MQLARTICLES_HASHMAP_MASK_EMPTY;
|
|
|
|
|
const ulong mask_hash_empty = TSNTABLES_SWAR_HAS(has_mask_emptry);
|
|
|
|
|
if(mask_hash_empty != 0)
|
2026-07-21 10:59:01 -05:00
|
|
|
return false; // Empty aqui...
|
2026-07-19 08:34:18 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
i = (i + 1) & group_f;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-07-21 10:59:01 -05:00
|
|
|
#define TSN_FASTHASHMAP_MACRO_U_S \
|
|
|
|
|
const uint group_f = m_num_groups - 1;\
|
|
|
|
|
uint i = uint(hash & group_f); \
|
|
|
|
|
const uchar h2 = uchar(hash >> 57);\
|
|
|
|
|
const ulong mask_hashes_finals = h2 * 0x0101010101010101; \
|
|
|
|
|
for(int it = 0; it < m_num_groups; it++) \
|
|
|
|
|
{ \
|
|
|
|
|
const ulong has_mask_hash = m_meta[i] ^ mask_hashes_finals; \
|
|
|
|
|
ulong mask_hash = TSNTABLES_SWAR_HAS(has_mask_hash); \
|
|
|
|
|
while(mask_hash != 0) \
|
|
|
|
|
{ \
|
|
|
|
|
const ulong flag = TSNTABLES_SWAR_64_DEJAR_SOLO_MINUS_SIG_BYTE(mask_hash); \
|
|
|
|
|
const int slot = int(i << 3) + (TSNTABLES_SWAR_64_GET_BIT(flag) >> 3);
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#define TSN_FASTHASHMAP_MACRO_U_E \
|
|
|
|
|
mask_hash &= (mask_hash - 1); \
|
|
|
|
|
} \
|
|
|
|
|
const ulong has_mask_emptry = m_meta[i] ^ MQLARTICLES_HASHMAP_MASK_EMPTY; \
|
|
|
|
|
const ulong mask_hash_empty = TSNTABLES_SWAR_HAS(has_mask_emptry); \
|
|
|
|
|
if(mask_hash_empty != 0) \
|
|
|
|
|
return -1; \
|
|
|
|
|
i = (i + 1) & group_f; \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2026-07-19 08:34:18 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename TPar, typename TKey, typename TBase>
|
2026-07-21 10:59:01 -05:00
|
|
|
int CFastHashTableBase::Find(const ulong hash) const
|
2026-07-19 08:34:18 -05:00
|
|
|
{
|
|
|
|
|
//---
|
2026-07-21 10:59:01 -05:00
|
|
|
TSN_FASTHASHMAP_MACRO_U_S
|
|
|
|
|
#ifndef TSN_MQLARTICLES_USE_KEY
|
|
|
|
|
if(m_table[slot].hash == hash)
|
|
|
|
|
return slot;
|
|
|
|
|
#else
|
|
|
|
|
if(TBase::Eq(m_table[slot].key, key))
|
|
|
|
|
return slot;
|
|
|
|
|
#endif
|
|
|
|
|
TSN_FASTHASHMAP_MACRO_U_E
|
2026-07-19 08:34:18 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-07-21 10:59:01 -05:00
|
|
|
return -1;
|
|
|
|
|
}
|
2026-07-19 08:34:18 -05:00
|
|
|
|
|
|
|
|
|
2026-07-21 10:59:01 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename TPar, typename TKey, typename TBase>
|
|
|
|
|
int CFastHashTableBase::Find(const TKey& key) const
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
const ulong hash = TBase::Hash(key);
|
2026-07-19 08:34:18 -05:00
|
|
|
|
2026-07-21 10:59:01 -05:00
|
|
|
//---
|
|
|
|
|
TSN_FASTHASHMAP_MACRO_U_S
|
|
|
|
|
#ifndef TSN_MQLARTICLES_USE_KEY
|
|
|
|
|
if(m_table[slot].hash == hash)
|
|
|
|
|
return slot;
|
|
|
|
|
#else
|
|
|
|
|
if(TBase::Eq(m_table[slot].key, key))
|
|
|
|
|
return slot;
|
|
|
|
|
#endif
|
|
|
|
|
TSN_FASTHASHMAP_MACRO_U_E
|
|
|
|
|
|
|
|
|
|
//---
|
2026-07-19 08:34:18 -05:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-21 10:59:01 -05:00
|
|
|
|
2026-07-19 08:34:18 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename TCtx, typename TKey>
|
|
|
|
|
struct CFastHashTableIteratorBase
|
|
|
|
|
{
|
|
|
|
|
TCtx* m_ctx;
|
|
|
|
|
ulong m_current_mask;
|
2026-07-19 22:56:49 -05:00
|
|
|
int m_num_groups;
|
2026-07-19 08:34:18 -05:00
|
|
|
int m_group_index;
|
|
|
|
|
int m_current_slot;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CFastHashTableIteratorBase(TCtx* ptr)
|
|
|
|
|
: m_ctx(ptr), m_current_mask(0), m_num_groups(ptr.m_num_groups), m_group_index(-1), m_current_slot(0)
|
|
|
|
|
{
|
|
|
|
|
Next();
|
2026-07-19 22:56:49 -05:00
|
|
|
}
|
|
|
|
|
CFastHashTableIteratorBase()
|
|
|
|
|
: m_ctx(NULL), m_current_mask(0), m_num_groups(0), m_group_index(-1), m_current_slot(0)
|
|
|
|
|
{
|
2026-07-19 08:34:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
__forceinline bool IsValid() const { return m_group_index < m_num_groups; }
|
|
|
|
|
void Kill() { m_group_index = m_num_groups; }
|
|
|
|
|
void Next();
|
|
|
|
|
|
|
|
|
|
//---
|
2026-07-21 10:59:01 -05:00
|
|
|
__forceinline ulong Hash() const { return m_ctx.m_table[m_current_slot].hash; }
|
2026-07-19 22:56:49 -05:00
|
|
|
__forceinline TKey Key() const { return m_ctx.m_table[m_current_slot].key; }
|
|
|
|
|
__forceinline int KeyLen() const { return StringLen(m_ctx.m_table[m_current_slot].key); }
|
2026-07-19 08:34:18 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
template <typename TCtx, typename TKey>
|
|
|
|
|
void CFastHashTableIteratorBase::Next()
|
|
|
|
|
{
|
|
|
|
|
//--- Solo si esta vacia...
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
|
|
|
|
if(m_current_mask != 0)
|
|
|
|
|
{
|
|
|
|
|
const ulong flag = TSNTABLES_SWAR_64_DEJAR_SOLO_MINUS_SIG_BYTE(m_current_mask);
|
|
|
|
|
m_current_slot = (m_group_index << 3) + TSNTABLES_SWAR_64_GET_BYTE(flag);
|
|
|
|
|
m_current_mask &= (m_current_mask - 1);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_group_index++;
|
|
|
|
|
if(m_group_index >= m_num_groups)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_current_mask = (m_ctx.m_meta[m_group_index] & MQLARTICLES_HASHMAP_MASK_HIGH_BIT) ^ MQLARTICLES_HASHMAP_MASK_HIGH_BIT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-07-21 11:09:28 -05:00
|
|
|
#endif // FASTCOLLECTIONSBYLEO_COLHASH_HASHBASES_MAIN_MQH
|