blob: 23484a7f50ef9bed8267bc1fb7758b9a20b3d0a2 [file]
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <vp4.h>
#include <vint.h>
#include "conf.h"
// 定义PAD8宏
#ifndef PAD8
#define PAD8(_x_) (((_x_) + 7) / 8)
#endif
const unsigned TEST_SIZE = 512;
#ifdef __AVX2__
void generate_test_data(unsigned* raw_values, unsigned n, unsigned char* encoded_data,
unsigned* out_size) {
// 使用p4nd1enc256v32编码原始数据
size_t end_ptr = p4nd1enc256v32(raw_values, n, encoded_data);
// 计算编码后数据大小
*out_size = end_ptr;
}
#endif
#define _1vbxget32(_ip_, _x_, _act_) do { _x_ = (unsigned)(*_ip_++);\
if(!(_x_ & 0x80u)) { _act_;}\
else if(!(_x_ & 0x40u)) { _x_ = bswap16(ctou16(_ip_ - 1) & 0xff3fu); _ip_++; _act_;}\
else if(!(_x_ & 0x20u)) { _x_ = (_x_ & 0x1f)<<16 | ctou16(_ip_); _ip_ += 2; _act_;}\
else if(!(_x_ & 0x10u)) { _x_ = bswap32(ctou32(_ip_-1) & 0xffffff0fu); _ip_ += 3; _act_;}\
else { _x_ = (unsigned long long)((_x_) & 0x07)<<32 | ctou32(_ip_); _ip_ += 4; _act_;}\
} while(0)
#define xvbxget32(_ip_, _x_) _1vbxget32(_ip_, _x_, ;)
// 用于快速得到 10^k 的一个表,避免多次调用 pow
// 注意 10^10=10000000000 需要 64 位才能存
static const uint64_t g_pow10[] = {
1ULL, // 10^0
10ULL, // 10^1
100ULL, // 10^2
1000ULL, // 10^3
10000ULL, // 10^4
100000ULL, // 10^5
1000000ULL, // 10^6
10000000ULL, // 10^7
100000000ULL, // 10^8
1000000000ULL,// 10^9
10000000000ULL// 10^10
};
// 计算 10^(floor(b/3)),若超出 g_pow10 范围可再加判断
static inline uint64_t get_pow10_for_b(unsigned b) {
// floor(b/3)
unsigned idx = b / 3;
if (idx >= sizeof(g_pow10)/sizeof(g_pow10[0])) {
// 超过预置表最大 10^10,就固定返回 10^10 或自行处理
return g_pow10[10];
}
return g_pow10[idx];
}
// 计算 2^b 的函数
static inline unsigned power2(unsigned b) {
// (1U << b) 当 b=32 时也可能溢出,你可自行判断
return (1U << b);
}
/**
* @param values 输出数组
* @param n 要生成的数据个数
* @param b 当前位宽
* @param with_exception 0=无异常,1=有异常
*/
void generate_raw_data_for_bitwidth(unsigned* values, unsigned n,
unsigned b, int with_exception)
{
if (n == 0) return;
if (!with_exception) {
// =====================================
// 无异常模式:递增序列
// =====================================
// 1) 先给一个随机初始值 base (你也可随意决定)
unsigned base = rand() % 1000;
values[0] = base;
// 2) 根据 b 分段决定“增量最大范围”
unsigned inc_range;
if (b < 4) {
// b=0 => 2^0=1, b=1 =>2, b=2 =>4, b=3=>8
inc_range = power2(b);
} else {
// b>=4 => 用10^(floor(b/3)) => 10,100,1000,...
uint64_t r = get_pow10_for_b(b);
// 这里最好判断 r 是否超出 unsigned 范围
// 若测试场景不会特别大,可以直接转为 unsigned
if (r > 0xFFFFFFFFULL) {
r = 0xFFFFFFFFULL; // 避免溢出
}
inc_range = (unsigned)r;
}
// 3) 生成递增序列
for (unsigned i = 1; i < n; i++) {
// +1 是为了避免 0 增量的情况
unsigned inc = 1 + rand() % inc_range;
base += inc;
values[i] = base;
}
} else {
// =====================================
// 有异常模式:直接随机
// =====================================
// 观察示例得知:
// - b=0 => rand()%2
// - b=2 => rand()%4
// - b=3 => rand()%10
// - b=7 => rand()%100
// - b=10 => rand()%1000
// - b=13 => rand()%10000
// => 规律:当 b >= 3 用 10^(floor(b/3));当 b < 3 用特殊处理
uint64_t val_range = 0; // 用 64 位临时存,最后再转回 unsigned
if (b == 0) {
val_range = 2; // 0..1
}
else if (b == 1) {
// 你没给 b=1 的具体例子,这里假设跟 b=0 一样 => range=2
val_range = 2; // 0..1
}
else if (b == 2) {
val_range = 4; // 0..3
}
else {
// b>=3 => 用 10^(floor(b/3))
val_range = get_pow10_for_b(b);
// 同样检查一下是否超过 unsigned
if (val_range > 0xFFFFFFFFULL) {
val_range = 0xFFFFFFFFULL;
}
}
// 直接随机
for (unsigned i = 0; i < n; i++) {
unsigned x = (unsigned)(rand() % (unsigned)val_range);
values[i] = x;
}
}
}
/**
* 生成 n 个有符号数:
* - b<3: 范围很小(±(1<<b) 之类)
* - b>=3: 直接从 ±(10^(floor(b/3))) 随机, 并包含一定的负值
*
* with_exception=0 => 生成一个“有序/有限范围”
* with_exception=1 => 生成一个“更大随机范围” (你可自定义)
*/
static void generate_raw_signed_data_for_zigzag(unsigned *values,
unsigned n,
unsigned b,
int with_exception)
{
if (n == 0) return;
// srand(...) 在外部一次初始化
uint64_t val_range = 1;
if (b < 3) {
// 例如 b=0 =>±1, b=1=>±2, b=2=>±4
val_range = (1ULL << b);
} else {
// b>=3 => use get_pow10_for_b(b) => 10^(floor(b/3))
val_range = get_pow10_for_b(b); // 参考你贴的 delta pfor
if(val_range > 0x7fffffffULL) {
val_range = 0x7fffffffULL; // 避免溢出 32-bit
}
}
for(unsigned i=0; i<n; i++){
// 先产生 0..val_range-1
int32_t x = (int32_t)(rand() % (unsigned)val_range);
// 随机决定正负
if(with_exception) {
// 例如 50% 概率取反
if((rand() & 1) == 1) x = -x;
} else {
// 不带异常 => 大部分正, 也可以小概率负
if((rand()%10)==0) x = -x;
}
values[i] = x;
}
}
#ifdef __AVX2__
void run_testZigzag(unsigned b,
int with_exception,
unsigned TEST_SIZE,
unsigned *raw_values,
unsigned char *encoded_data,
unsigned *decoded1,
unsigned *decoded2)
{
printf("Zigzag 测试: 位宽 b=%u, with_exception=%d\n", b, with_exception);
// 1) 生成带正负 raw data
generate_raw_signed_data_for_zigzag(raw_values, TEST_SIZE, b, with_exception);
unsigned encoded_size = p4nzenc256v32(raw_values, TEST_SIZE, encoded_data);
// 获取编码头部信息(例如起始值等)
unsigned start;
unsigned char* copy = encoded_data;
xvbxget32(copy, start);
unsigned char encoded_b = copy[0]; // 编码后的第一个字节为位宽
if((encoded_b & 0x40)) {
encoded_b &= 0x3f;
} else {
if(encoded_b & 0x80) {
encoded_b &= 0x7f;
}
}
printf(" 编码参数: 位宽 b=%u, 起始值 start=%u, 编码大小=%u字节\n", encoded_b, start, encoded_size);
// 3) decode => two versions for cross-check
// (here we define "decoded1" from "bitzunpack256v32...??" and "decoded2" from "bitzunpack256scalarv32Zigzag"??)
memset(decoded1,0,TEST_SIZE*sizeof(unsigned));
memset(decoded2,0,TEST_SIZE*sizeof(unsigned));
// "decoded1" => maybe vector version if you have it? e.g. "bitzunpack256v32(in,b, out,??)"
// "decoded2" => scalar version ?
// for demonstration, we do the same decode to compare:
p4nzdec256v32(encoded_data, TEST_SIZE, decoded1);
p4nzdec256scalarv32(encoded_data, TEST_SIZE, decoded2);
// 4) compare mismatch
int mismatch=0;
for(unsigned i=0;i<TEST_SIZE;i++){
if(decoded1[i] != decoded2[i]){
if(mismatch<10)
printf(" mismatch at i=%u: dec1=%d, dec2=%d\n", i, decoded1[i], decoded2[i]);
mismatch++;
}
}
if(mismatch==0){
printf(" decode1 & decode2 match!\n");
// verify with original
int error=0;
for(unsigned i=0;i<TEST_SIZE;i++){
if(decoded1[i] != raw_values[i]){
if(error<10)
printf(" raw mismatch at i=%u: raw=%d, dec=%d\n", i,raw_values[i], decoded1[i]);
error++;
}
}
if(error==0) printf(" and match raw data!\n");
else printf(" total %d raw mismatch\n", error);
} else {
printf(" total mismatch=%d\n", mismatch);
}
printf("\n");
}
void run_test(unsigned b, int with_exception, unsigned TEST_SIZE,
unsigned* raw_values, unsigned char* encoded_data,
unsigned* decoded1, unsigned* decoded2) {
printf("测试: 位宽 b=%u, 异常%s\n", b, (with_exception ? "有" : "无"));
// 生成符合当前 b 与异常模式的原始数据
generate_raw_data_for_bitwidth(raw_values, TEST_SIZE, b, with_exception);
unsigned encoded_size;
generate_test_data(raw_values, TEST_SIZE, encoded_data, &encoded_size);
// 获取编码头部信息(例如起始值等)
unsigned start;
unsigned char* copy = encoded_data;
xvbxget32(copy, start);
unsigned char encoded_b = copy[0]; // 编码后的第一个字节为位宽
if((encoded_b & 0x40)) {
encoded_b &= 0x3f;
} else {
if(encoded_b & 0x80) {
encoded_b &= 0x7f;
}
}
printf(" 编码参数: 位宽 b=%u, 起始值 start=%u, 编码大小=%u字节\n", encoded_b, start, encoded_size);
// 清空解码缓冲区
memset(decoded1, 0, TEST_SIZE * sizeof(unsigned));
memset(decoded2, 0, TEST_SIZE * sizeof(unsigned));
// 调用两种解码方式
p4nd1dec256v32(encoded_data, TEST_SIZE, decoded1);
p4nd1dec256scalarv32(encoded_data, TEST_SIZE, decoded2);
// 比较两个解码结果是否匹配
int mismatch = 0;
for (unsigned i = 0; i < TEST_SIZE; i++) {
if (decoded1[i] != decoded2[i]) {
if (mismatch < 10)
printf(" 不匹配: 索引 %u, 原始值=%u, 原始解码=%u, 标量解码=%u\n",
i, raw_values[i], decoded1[i], decoded2[i]);
mismatch++;
}
}
if (mismatch == 0) {
printf(" 通过: 所有解码值匹配!\n");
// 验证解码值与原始数据是否一致
int error = 0;
for (unsigned i = 0; i < TEST_SIZE && error < 10; i++) {
if (decoded1[i] != raw_values[i]) {
printf(" 编码/解码错误: 索引 %u, 原始值=%u, 解码值=%u\n",
i, raw_values[i], decoded1[i]);
error++;
}
}
if (error == 0)
printf(" 验证通过: 解码结果与原始数据一致\n");
} else {
printf(" 失败: 有 %d 个值不匹配\n", mismatch);
printf(" 原始数据 (前16个): ");
for (unsigned i = 0; i < 16 && i < TEST_SIZE; i++)
printf("%u ", raw_values[i]);
printf("...\n");
printf(" 原始解码 (前16个): ");
for (unsigned i = 0; i < 16 && i < TEST_SIZE; i++)
printf("%u ", decoded1[i]);
printf("...\n");
printf(" 标量解码 (前16个): ");
for (unsigned i = 0; i < 16 && i < TEST_SIZE; i++)
printf("%u ", decoded2[i]);
printf("...\n");
}
printf("\n");
}
void testZigZag()
{
const unsigned TEST_SIZE=512; //or512
unsigned *raw_values= (unsigned*) malloc(TEST_SIZE*sizeof(unsigned));
unsigned *decoded1= (unsigned*) malloc(TEST_SIZE*sizeof(unsigned));
unsigned *decoded2= (unsigned*) malloc(TEST_SIZE*sizeof(unsigned));
unsigned char* encoded_data= (unsigned char*) malloc(TEST_SIZE*4+ 10); //maybe
srand((unsigned)time(NULL));
printf("开始测试 p4nzdec256v32...\n");
for(unsigned b=0; b<=32; b++){
run_testZigzag(b,0, TEST_SIZE, raw_values, encoded_data, decoded1, decoded2);
run_testZigzag(b,1, TEST_SIZE, raw_values, encoded_data, decoded1, decoded2);
}
free(raw_values);
free(decoded1);
free(decoded2);
free(encoded_data);
}
void test_p4nd1dec256v32() {
const unsigned TEST_SIZE = 512;
// 分配缓冲区
unsigned* raw_values = (unsigned*)malloc(TEST_SIZE * sizeof(unsigned));
unsigned char* encoded_data = (unsigned char*)malloc(TEST_SIZE * sizeof(unsigned) * 2);
unsigned* decoded1 = (unsigned*)malloc(TEST_SIZE * sizeof(unsigned));
unsigned* decoded2 = (unsigned*)malloc(TEST_SIZE * sizeof(unsigned));
srand((unsigned)time(NULL));
printf("开始测试 p4nd1dec256v32...\n");
// 对 b = 0 到 31 测试两种模式:无异常和有异常
for (unsigned b = 0; b < 32; b++) {
run_test(b, 0, TEST_SIZE, raw_values, encoded_data, decoded1, decoded2);
run_test(b, 1, TEST_SIZE, raw_values, encoded_data, decoded1, decoded2);
}
// 对 b == 32 只测试无异常情况
run_test(32, 0, TEST_SIZE, raw_values, encoded_data, decoded1, decoded2);
free(raw_values);
free(encoded_data);
free(decoded1);
free(decoded2);
printf("测试完成!\n");
}
#endif
int main() {
#ifdef __AVX2__
test_p4nd1dec256v32();
testZigZag();
//test_until_b1_achieved_improved();
#endif
return 0;
}