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.
Zero/ZeroLevel.HNSW/Services/Quantizator.cs

109 lines
3.2 KiB

using System;
namespace ZeroLevel.HNSW.Services
{
public class Quantizator
{
private readonly float _min;
private readonly float _max;
private readonly float _diff;
public Quantizator(float min, float max)
{
_min = min;
_max = max;
_diff = _max - _min;
}
public byte[] Quantize(float[] v)
{
var result = new byte[v.Length];
for (int i = 0; i < v.Length; i++)
{
result[i] = _quantizeInRange(v[i]);
}
return result;
}
public int[] QuantizeToInt(float[] v)
{
var diff = v.Length % 4;
int count = (v.Length - diff) / 4;
var result = new int[((diff == 0) ? 0 : 1) + (v.Length / 4)];
byte[] buf = new byte[4];
int i = 0;
for (; i < count * 4; i += 4)
{
buf[0] = _quantizeInRange(v[i]);
buf[1] = _quantizeInRange(v[i + 1]);
buf[2] = _quantizeInRange(v[i + 2]);
buf[3] = _quantizeInRange(v[i + 3]);
result[(i >> 2)] = BitConverter.ToInt32(buf);
}
if (diff != 0)
{
for (var j = 0; j < diff; j++)
{
buf[j] = _quantizeInRange(v[i + j]);
}
for (var j = diff; j < 4; j++)
{
buf[j] = 0;
}
result[(i >> 2)] = BitConverter.ToInt32(buf);
}
return result;
}
public long[] QuantizeToLong(float[] v)
{
var diff = v.Length % 8;
int count = (v.Length - diff) / 8;
var result = new long[((diff == 0) ? 0 : 1) + (v.Length / 8)];
byte[] buf = new byte[8];
int i = 0;
for (; i < count * 8; i += 8)
{
buf[0] = _quantizeInRange(v[i + 0]);
buf[1] = _quantizeInRange(v[i + 1]);
buf[2] = _quantizeInRange(v[i + 2]);
buf[3] = _quantizeInRange(v[i + 3]);
buf[4] = _quantizeInRange(v[i + 4]);
buf[5] = _quantizeInRange(v[i + 5]);
buf[6] = _quantizeInRange(v[i + 6]);
buf[7] = _quantizeInRange(v[i + 7]);
result[(i >> 3)] = BitConverter.ToInt64(buf);
}
if (diff != 0)
{
for (var j = 0; j < diff; j++)
{
buf[j] = _quantizeInRange(v[i + j]);
}
for (var j = diff; j < 8; j++)
{
buf[j] = 0;
}
result[(i >> 3)] = BitConverter.ToInt64(buf);
}
return result;
}
//Map x in [0,1] to {0, 1, ..., 255}
private byte _quantize(float x)
{
x = (int)Math.Floor(256 * x);
if (x < 0) return 0;
else if (x > 255) return 255;
else return (byte)x;
}
//Map x in [min,max] to {0, 1, ..., 255}
private byte _quantizeInRange(float x)
{
return _quantize((x - _min) / (_diff));
}
}
}

Powered by TurnKey Linux.