mirror of https://github.com/ogoun/Zero.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
3.1 KiB
108 lines
3.1 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using ZeroLevel.Services.Serialization;
|
|
|
|
namespace ZeroLevel.HNSW
|
|
{
|
|
internal sealed class ReadOnlyCompactBiDirectionalLinksSet
|
|
: IBinarySerializable, IDisposable
|
|
{
|
|
private const int HALF_LONG_BITS = 32;
|
|
|
|
private Dictionary<int, int[]> _set = new Dictionary<int, int[]>();
|
|
|
|
internal int Count => _set.Count;
|
|
|
|
internal IEnumerable<int> FindLinksForId(int id)
|
|
{
|
|
if (_set.ContainsKey(id))
|
|
{
|
|
return _set[id];
|
|
}
|
|
return Enumerable.Empty<int>();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_set.Clear();
|
|
_set = null;
|
|
}
|
|
|
|
public void Serialize(IBinaryWriter writer)
|
|
{
|
|
writer.WriteBoolean(false); // false - set without weights
|
|
writer.WriteInt32(_set.Count);
|
|
foreach (var record in _set)
|
|
{
|
|
writer.WriteInt32(record.Key);
|
|
writer.WriteCollection(record.Value);
|
|
}
|
|
}
|
|
|
|
public void Deserialize(IBinaryReader reader)
|
|
{
|
|
_set.Clear();
|
|
_set = null;
|
|
if (reader.ReadBoolean() == false)
|
|
{
|
|
var count = reader.ReadInt32();
|
|
_set = new Dictionary<int, int[]>(count);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
var key = reader.ReadInt32();
|
|
var value = reader.ReadInt32Array();
|
|
_set.Add(key, value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var count = reader.ReadInt32();
|
|
_set = new Dictionary<int, int[]>(count);
|
|
|
|
// hack, We know that an sortedset has been saved
|
|
long key;
|
|
int id1, id2;
|
|
var prevId = -1;
|
|
var set = new HashSet<int>();
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
key = reader.ReadLong();
|
|
id1 = (int)(key >> HALF_LONG_BITS);
|
|
id2 = (int)(key - (((long)id1) << HALF_LONG_BITS));
|
|
|
|
reader.ReadFloat(); // SKIP
|
|
|
|
if (prevId == -1)
|
|
{
|
|
prevId = id1;
|
|
if (id1 != id2)
|
|
{
|
|
set.Add(id2);
|
|
}
|
|
}
|
|
else if (prevId != id1)
|
|
{
|
|
_set.Add(prevId, set.ToArray());
|
|
set.Clear();
|
|
prevId = id1;
|
|
}
|
|
else
|
|
{
|
|
if (id1 != id2)
|
|
{
|
|
set.Add(id2);
|
|
}
|
|
}
|
|
}
|
|
if (set.Count > 0)
|
|
{
|
|
_set.Add(prevId, set.ToArray());
|
|
set.Clear();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|