mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-27 15:00:18 +00:00
Compare commits
No commits in common. "fcc23f65cc739b767aa860aad75aa5ce2b45df66" and "03e368b7551db31701543ff140f5f796c4406a49" have entirely different histories.
fcc23f65cc
...
03e368b755
@ -1,31 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "pocketpy/export.h"
|
|
||||||
#include "pocketpy/common/vector.h"
|
|
||||||
typedef struct c11_chunkedvector_chunk {
|
|
||||||
int length;
|
|
||||||
int capacity;
|
|
||||||
void* data;
|
|
||||||
} c11_chunkedvector_chunk;
|
|
||||||
|
|
||||||
typedef struct c11_chunkedvector {
|
|
||||||
c11_vector /*T=c11_chunkedvector_chunk*/ chunks;
|
|
||||||
int length;
|
|
||||||
int capacity;
|
|
||||||
int elem_size;
|
|
||||||
int initial_chunks;
|
|
||||||
} c11_chunkedvector;
|
|
||||||
|
|
||||||
// chunks[0]: size=1, total_capacity=1
|
|
||||||
// chunks[1]: size=2, total_capacity=3
|
|
||||||
// chunks[2]: size=4, total_capacity=7
|
|
||||||
// chunks[3]: size=8, total_capacity=15
|
|
||||||
// chunks[4]: size=16, total_capacity=31
|
|
||||||
// chunks[5]: size=32, total_capacity=63
|
|
||||||
// ...
|
|
||||||
// chunks[n]: size=2^n, total_capacity=2^(n+1)-1
|
|
||||||
|
|
||||||
void c11_chunkedvector__ctor(c11_chunkedvector* self, int elem_size, int initial_chunks);
|
|
||||||
void c11_chunkedvector__dtor(c11_chunkedvector* self);
|
|
||||||
void* c11_chunkedvector__emplace(c11_chunkedvector* self);
|
|
||||||
void* c11_chunkedvector__at(c11_chunkedvector* self, int index);
|
|
||||||
@ -1,86 +0,0 @@
|
|||||||
#include "pocketpy/common/chunkedvector.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "pocketpy/common/utils.h"
|
|
||||||
#include "pocketpy/config.h"
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#include <intrin.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline static int c11_bit_length(unsigned long x) {
|
|
||||||
#if(defined(__clang__) || defined(__GNUC__))
|
|
||||||
return x == 0 ? 0 : (int)sizeof(unsigned long) * 8 - __builtin_clzl(x);
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
static_assert(sizeof(unsigned long) <= 4, "unsigned long is greater than 4 bytes");
|
|
||||||
unsigned long msb;
|
|
||||||
if(_BitScanReverse(&msb, x)) { return (int)msb + 1; }
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
const int BIT_LENGTH_TABLE[32] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
|
|
||||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
|
|
||||||
int msb = 0;
|
|
||||||
while(x >= 32) {
|
|
||||||
msb += 6;
|
|
||||||
x >>= 6;
|
|
||||||
}
|
|
||||||
msb += BIT_LENGTH_TABLE[x];
|
|
||||||
return msb;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void c11_chunkedvector__ctor(c11_chunkedvector* self, int elem_size, int initial_chunks) {
|
|
||||||
if(initial_chunks < 5) initial_chunks = 5;
|
|
||||||
c11_vector__ctor(&self->chunks, sizeof(c11_chunkedvector_chunk));
|
|
||||||
self->length = 0;
|
|
||||||
self->capacity = (1U << (unsigned int)initial_chunks) - 1U;
|
|
||||||
self->elem_size = elem_size;
|
|
||||||
self->initial_chunks = initial_chunks;
|
|
||||||
void* chunks_data = PK_MALLOC(elem_size * ((1U << (unsigned int)initial_chunks) - 1));
|
|
||||||
for(int i = 0; i < initial_chunks; i++) {
|
|
||||||
// TODO: optimize?
|
|
||||||
c11_chunkedvector_chunk chunk = {.length = 0,
|
|
||||||
.capacity = 1U << i,
|
|
||||||
.data = (char*)chunks_data + elem_size * ((1U << i) - 1U)};
|
|
||||||
c11_vector__push(c11_chunkedvector_chunk, &self->chunks, chunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void c11_chunkedvector__dtor(c11_chunkedvector* self) {
|
|
||||||
for(int index = self->initial_chunks; index < self->chunks.length; index++) {
|
|
||||||
c11_chunkedvector_chunk* chunk = c11__at(c11_chunkedvector_chunk, &self->chunks, index);
|
|
||||||
PK_FREE(chunk->data);
|
|
||||||
}
|
|
||||||
c11_chunkedvector_chunk* initial_chunk = c11__at(c11_chunkedvector_chunk, &self->chunks, 0);
|
|
||||||
PK_FREE(initial_chunk->data);
|
|
||||||
c11_vector__dtor(&self->chunks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* c11_chunkedvector__emplace(c11_chunkedvector* self) {
|
|
||||||
if(self->length == self->capacity) {
|
|
||||||
#ifndef NDEBUG
|
|
||||||
c11_chunkedvector_chunk last_chunk = c11_vector__back(c11_chunkedvector_chunk, &self->chunks);
|
|
||||||
assert(last_chunk.capacity == last_chunk.length);
|
|
||||||
#endif
|
|
||||||
c11_chunkedvector_chunk chunk = {
|
|
||||||
.length = 0,
|
|
||||||
.capacity = 1U << (unsigned int)self->chunks.length,
|
|
||||||
.data = PK_MALLOC(self->elem_size * ((1U << (unsigned int)self->chunks.length)))};
|
|
||||||
self->capacity += chunk.capacity;
|
|
||||||
c11_vector__push(c11_chunkedvector_chunk, &self->chunks, chunk);
|
|
||||||
}
|
|
||||||
int last_chunk_index = c11_bit_length(self->length + 1) - 1;
|
|
||||||
c11_chunkedvector_chunk* last_chunk =
|
|
||||||
c11__at(c11_chunkedvector_chunk, &self->chunks, last_chunk_index);
|
|
||||||
void* p = (char*)last_chunk->data + self->elem_size * last_chunk->length;
|
|
||||||
last_chunk->length++;
|
|
||||||
self->length++;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* c11_chunkedvector__at(c11_chunkedvector* self, int index) {
|
|
||||||
int chunk_index = c11_bit_length(index + 1) - 1;
|
|
||||||
c11_chunkedvector_chunk* chunk = c11__at(c11_chunkedvector_chunk, &self->chunks, chunk_index);
|
|
||||||
return (char*)chunk->data + (index + 1 - (1U << (unsigned int)chunk_index)) * self->elem_size;
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user