From e36f5699fef6487fac8576d6f824109615a71cf1 Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Wed, 24 Apr 2024 13:16:37 -0400 Subject: [PATCH] rank true/false working --- flake.lock | 48 ++++++++++++------------ flake.nix | 98 ++++++++++++++++++++++++------------------------- src/sparsemap.c | 39 +++++++++++++------- tests/test.c | 14 +------ 4 files changed, 98 insertions(+), 101 deletions(-) diff --git a/flake.lock b/flake.lock index c8aedb6..f0ad25e 100644 --- a/flake.lock +++ b/flake.lock @@ -1,43 +1,25 @@ { "nodes": { - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "nixpkgs": { "locked": { - "lastModified": 1712192574, - "narHash": "sha256-LbbVOliJKTF4Zl2b9salumvdMXuQBr2kuKP5+ZwbYq4=", + "lastModified": 1701282334, + "narHash": "sha256-MxCVrXY6v4QmfTwIysjjaX0XUhqBbxTWWB4HXtDYsdk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f480f9d09e4b4cf87ee6151eba068197125714de", + "rev": "057f9aecfb71c4437d2b27d3323df7f93c010b7e", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "23.11", "repo": "nixpkgs", "type": "github" } }, "root": { "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "utils": "utils" } }, "systems": { @@ -54,6 +36,24 @@ "repo": "default", "type": "github" } + }, + "utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 041d550..0c39844 100644 --- a/flake.nix +++ b/flake.nix @@ -2,58 +2,54 @@ description = "A sparse bitmapped index library in C."; inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - flake-utils.url = "github:numtide/flake-utils"; + # nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + nixpkgs.url = "github:NixOS/nixpkgs/23.11"; + utils.url = "github:numtide/flake-utils"; + utils.inputs.nixpkgs.follows = "nixpkgs"; }; - outputs = - { self - , nixpkgs - , flake-utils - , ... - }: - flake-utils.lib.eachDefaultSystem (system: - let - pkgs = import nixpkgs { - inherit system; - config = { allowUnfree = true; }; - }; - supportedSystems = [ "x86_64-linux" ]; - forAllSystems = nixpkgs.lib.genAttrs supportedSystems; - nixpkgsFor = forAllSystems (system: import nixpkgs { - inherit system; - overlays = [ self.overlay ]; - }); - in { - pkgs = import nixpkgs { - inherit system; - devShell = nixpkgs.legacyPackages.${system} { - pkgs.mkShell = { - nativeBuildInputs = with pkgs.buildPackages; [ - act - autoconf - clang - ed - gcc - gdb - gettext - graphviz-nox - libtool - m4 - perl - pkg-config - python3 - ripgrep - valgrind - ]; - buildInputs = with pkgs; [ - libbacktrace - glibc.out - glibc.static - ]; - }; - DOCKER_BUILDKIT = 1; + outputs = { self, nixpkgs, ... } + @inputs: inputs.utils.lib.eachSystem [ + "x86_64-linux" "i686-linux" "aarch64-linux" "x86_64-darwin" + ] (system: + let pkgs = import nixpkgs { + inherit system; + overlays = []; + config.allowUnfree = true; }; - }; - }); + in { + devShell = pkgs.mkShell rec { + name = "sparsemap"; + packages = with pkgs; [ + act + autoconf + clang + ed + gcc + gdb + gettext + graphviz-nox + libtool + m4 + perl + pkg-config + python3 + ripgrep + valgrind + ]; + + buildInputs = with pkgs; [ + libbacktrace + glibc.out + glibc.static + ]; + + shellHook = let + icon = "f121"; + in '' + export PS1="$(echo -e '\u${icon}') {\[$(tput sgr0)\]\[\033[38;5;228m\]\w\[$(tput sgr0)\]\[\033[38;5;15m\]} (${name}) \\$ \[$(tput sgr0)\]" + ''; + }; + DOCKER_BUILDKIT = 1; + }); } diff --git a/src/sparsemap.c b/src/sparsemap.c index 466f3ef..672f009 100644 --- a/src/sparsemap.c +++ b/src/sparsemap.c @@ -490,6 +490,14 @@ __sm_chunk_map_rank(__sm_chunk_t *map, size_t *offset, size_t idx, size_t *pos, *pos = 0; + /* A chunk can only hold at most SM_CHUNK_MAX_CAPACITY bits, so if the + offset is larger than that, we're basically done. */ + if (*offset > SM_CHUNK_MAX_CAPACITY) { + *pos = SM_CHUNK_MAX_CAPACITY; + *offset -= SM_CHUNK_MAX_CAPACITY; + return 0; + } + register uint8_t *p = (uint8_t *)map->m_data; for (size_t i = 0; i < sizeof(sm_bitvec_t); i++, p++) { for (int j = 0; j < SM_FLAGS_PER_INDEX_BYTE; j++) { @@ -511,7 +519,7 @@ __sm_chunk_map_rank(__sm_chunk_t *map, size_t *offset, size_t idx, size_t *pos, *offset = 0; } } else { - *pos += idx; + *pos += idx + 1; if (value == false) { if (*offset > idx) { *offset = *offset - idx; @@ -538,7 +546,7 @@ __sm_chunk_map_rank(__sm_chunk_t *map, size_t *offset, size_t idx, size_t *pos, *offset = 0; } } else { - *pos += idx; + *pos += idx + 1; if (value == true) { if (*offset > idx) { *offset = *offset - idx; @@ -567,7 +575,7 @@ __sm_chunk_map_rank(__sm_chunk_t *map, size_t *offset, size_t idx, size_t *pos, ret += pc; *offset = (*offset > SM_BITS_PER_VECTOR) ? *offset - SM_BITS_PER_VECTOR : 0; } else { - *pos += idx; + *pos += idx + 1; sm_bitvec_t mw; uint64_t mask; uint64_t idx_mask = (idx == 63) ? UINT64_MAX : ((uint64_t)1 << (idx + 1)) - 1; @@ -1326,8 +1334,10 @@ size_t sparsemap_rank_vec(sparsemap_t *map, size_t x, size_t y, bool value, sm_bitvec_t *vec) { assert(sparsemap_get_size(map) >= SM_SIZEOF_OVERHEAD); - size_t amt = 0, gap, pos = 0, result = 0, prev = 0, count = __sm_get_chunk_map_count(map); - uint8_t *p = __sm_get_chunk_map_data(map, 0); + size_t amt, gap, pos = 0, result = 0, prev = 0, count; + uint8_t *p; + + count = __sm_get_chunk_map_count(map); if (count == 0) { if (value == false) { @@ -1336,30 +1346,31 @@ sparsemap_rank_vec(sparsemap_t *map, size_t x, size_t y, bool value, sm_bitvec_t } } + p = __sm_get_chunk_map_data(map, 0); + for (size_t i = 0; i < count; i++) { sm_idx_t start = *(sm_idx_t *)p; - gap = start - (prev == 0 ? start : prev); - (void)gap; // TODO... necessary? + gap = start - prev; /* [prev, start), prev is the last bit examined 0-based */ /* Start of this chunk is greater than the end of the desired range. */ if (start > y) { + /* This chunk starts after our range [x, y]. */ if (value == true) { return result; } else { - /* This chunk starts after our range [x, y]. */ return result + (y - x) + 1; } } else { /* The range and this chunk overlap. */ if (value == false) { - if (x > start) { - x -= start; + if (x > gap) { + x -= gap; } else { - result += start - x; + result += gap - x; x = 0; } } } - prev = start; + prev = start - 1; p += sizeof(sm_idx_t); __sm_chunk_t chunk; __sm_chunk_map_init(&chunk, p); @@ -1372,9 +1383,9 @@ sparsemap_rank_vec(sparsemap_t *map, size_t x, size_t y, bool value, sm_bitvec_t /* Count any additional unset bits that fall outside the last chunk but within the range. */ if (value == false) { - size_t last = prev + pos - 1; + size_t last = prev + pos; if (y > last) { - result += y - last; + result += y - last - x; } } return result; diff --git a/tests/test.c b/tests/test.c index c75cde3..585494b 100644 --- a/tests/test.c +++ b/tests/test.c @@ -820,28 +820,18 @@ test_api_rank_false(const MunitParameter params[], void *data) } } - // one chunk means not so empty now! + // One chunk means not so empty now! sparsemap_idx_t hole = 4999; sparsemap_set(map, hole, true); -#if 1 for (int i = 0; i < 10000; i++) { for (int j = i; j < 10000; j++) { -#else - for (int i = 7041; i < 10000; i++) { - for (int j = 7040; j < 10000; j++) { -#endif int amt = j - i + 1 - ((hole >= i && j >= hole) ? 1 : 0); r = sparsemap_rank(map, i, j, false); -#ifdef DEBUG - if (r != amt) { - printf("\033[2K\r"); - printf("%d\t%d\t--\t%d\t%d", i, j, amt, r); - } -#endif assert_true(r == amt); } } + sparsemap_clear(map); sparsemap_set(map, 1, true); sparsemap_set(map, 11, true); r = sparsemap_rank(map, 0, 11, false);