Roaring bitmaps in C (and C++)

Overview

CRoaring Build Status Build status Build Status

Portable Roaring bitmaps in C (and C++) with full support for your favorite compiler (GNU GCC, LLVM's clang, Visual Studio). Included in the Awesome C list of open source C software.

Introduction

Bitsets, also called bitmaps, are commonly used as fast data structures. Unfortunately, they can use too much memory. To compensate, we often use compressed bitmaps.

Roaring bitmaps are compressed bitmaps which tend to outperform conventional compressed bitmaps such as WAH, EWAH or Concise. They are used by several major systems such as Apache Lucene and derivative systems such as Solr and Elasticsearch, Metamarkets' Druid, LinkedIn Pinot, Netflix Atlas, Apache Spark, OpenSearchServer, Cloud Torrent, Whoosh, InfluxDB, Pilosa, Bleve, Microsoft Visual Studio Team Services (VSTS), and eBay's Apache Kylin. The CRoaring library is used in several systems such as Apache Doris. The YouTube SQL Engine, Google Procella, uses Roaring bitmaps for indexing.

We published a peer-reviewed article on the design and evaluation of this library:

  • Roaring Bitmaps: Implementation of an Optimized Software Library, Software: Practice and Experience 48 (4), 2018 arXiv:1709.07821

Roaring bitmaps are found to work well in many important applications:

Use Roaring for bitmap compression whenever possible. Do not use other bitmap compression methods (Wang et al., SIGMOD 2017)

There is a serialized format specification for interoperability between implementations. Hence, it is possible to serialize a Roaring Bitmap from C++, read it in Java, modify it, serialize it back and read it in Go and Python.

Objective

The primary goal of the CRoaring is to provide a high performance low-level implementation that fully take advantage of the latest hardware. Roaring bitmaps are already available on a variety of platform through Java, Go, Rust... implementations. CRoaring is a library that seeks to achieve superior performance by staying close to the latest hardware.

(c) 2016-... The CRoaring authors.

Requirements

  • Linux, macOS, FreeBSD, Windows (MSYS2 and Microsoft Visual studio).
  • We test the library with ARM, x64/x86 and POWER processors. We only support little endian systems (big endian systems are vanishingly rare).
  • Recent C compiler supporting the C11 standard (GCC 4.8 or better or clang), there is also an optional C++ class that requires a C++ compiler supporting the C++11 standard.
  • CMake (to contribute to the project, users can rely on amalgamation/unity builds if they do not wish to use CMake).

Using a CMake subdirectory

If you like CMake, you can just drop CRoaring in your project as a subdirectory and get going. See our demonstration for further details.

Amalgamation/Unity Build

The CRoaring library can be amalgamated into a single source file that makes it easier for integration into other projects. Moreover, by making it possible to compile all the critical code into one compilation unit, it can improve the performance. For the rationale, please see the SQLite documentation, https://www.sqlite.org/amalgamation.html, or the corresponding Wikipedia entry (https://en.wikipedia.org/wiki/Single_Compilation_Unit). Users who choose this route, do not need to rely on CRoaring's build system (based on CMake).

We maintain pre-generated amalgamated files at https://github.com/lemire/CRoaringUnityBuild for your convenience.

To generate the amalgamated files yourself, you can invoke a bash script...

./amalgamation.sh

(Bash shells are standard under Linux and macOS. Bash shells are available under Windows as part of the  GitHub Desktop under the name Git Shell. So if you have cloned the CRoaring GitHub repository from within the GitHub Desktop, you can right-click on CRoaring, select Git Shell and then enter the above commands.)

It is not necessary to invoke the script in the CRoaring directory. You can invoke it from any directory where you want the amalgamation files to be written.

It will generate three files for C users: roaring.h, roaring.c and amalgamation_demo.c... as well as some brief instructions. The amalgamation_demo.c file is a short example, whereas roaring.h and roaring.c are "amalgamated" files (including all source and header files for the project). This means that you can simply copy the files roaring.h and roaring.c into your project and be ready to go! No need to produce a library! See the amalgamation_demo.c file.

For example, you can use the C code as follows:

#include <stdio.h>
#include "roaring.c"
int main() {
  roaring_bitmap_t *r1 = roaring_bitmap_create();
  for (uint32_t i = 100; i < 1000; i++) roaring_bitmap_add(r1, i);
  printf("cardinality = %d\n", (int) roaring_bitmap_get_cardinality(r1));
  roaring_bitmap_free(r1);
  return 0;
}

The script will also generate C++ files for C++ users, including an example. You can use the C++ as follows.

#include <iostream>

#include "roaring.hh"
#include "roaring64map.hh"

using namespace roaring;
int main() {
    Roaring r1;
    for (uint32_t i = 100; i < 1000; i++) {
        r1.add(i);
    }
    std::cout << "cardinality = " << r1.cardinality() << std::endl;

    Roaring64Map r2;
    for (uint64_t i = 18000000000000000100ull; i < 18000000000000001000ull;
         i++) {
        r2.add(i);
    }
    std::cout << "cardinality = " << r2.cardinality() << std::endl;
    return EXIT_SUCCESS;
}

If you prefer a silent output, you can use the following command to redirect stdout :

./amalgamation.sh > /dev/null

API

The C interface is found in the file include/roaring/roaring.h. We have C++ interface at cpp/roaring.hh.

Dealing with large volumes

Some users have to deal with large volumes of data. It may be important for these users to be aware of the addMany (C++) roaring_bitmap_or_many (C) functions as it is much faster and economical to add values in batches when possible. Furthermore, calling periodically the runOptimize (C++) or roaring_bitmap_run_optimize (C) functions may help.

Example (C)

#include <roaring/roaring.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

bool roaring_iterator_sumall(uint32_t value, void *param) {
    *(uint32_t *)param += value;
    return true;  // iterate till the end
}

int main() {
    // create a new empty bitmap
    roaring_bitmap_t *r1 = roaring_bitmap_create();
    // then we can add values
    for (uint32_t i = 100; i < 1000; i++) roaring_bitmap_add(r1, i);
    // check whether a value is contained
    assert(roaring_bitmap_contains(r1, 500));
    // compute how many bits there are:
    uint32_t cardinality = roaring_bitmap_get_cardinality(r1);
    printf("Cardinality = %d \n", cardinality);

    // if your bitmaps have long runs, you can compress them by calling
    // run_optimize
    uint32_t expectedsizebasic = roaring_bitmap_portable_size_in_bytes(r1);
    roaring_bitmap_run_optimize(r1);
    uint32_t expectedsizerun = roaring_bitmap_portable_size_in_bytes(r1);
    printf("size before run optimize %d bytes, and after %d bytes\n",
           expectedsizebasic, expectedsizerun);

    // create a new bitmap containing the values {1,2,3,5,6}
    roaring_bitmap_t *r2 = roaring_bitmap_of(5, 1, 2, 3, 5, 6);
    roaring_bitmap_printf(r2);  // print it

    // we can also create a bitmap from a pointer to 32-bit integers
    uint32_t somevalues[] = {2, 3, 4};
    roaring_bitmap_t *r3 = roaring_bitmap_of_ptr(3, somevalues);

    // we can also go in reverse and go from arrays to bitmaps
    uint64_t card1 = roaring_bitmap_get_cardinality(r1);
    uint32_t *arr1 = (uint32_t *)malloc(card1 * sizeof(uint32_t));
    assert(arr1 != NULL);
    roaring_bitmap_to_uint32_array(r1, arr1);
    roaring_bitmap_t *r1f = roaring_bitmap_of_ptr(card1, arr1);
    free(arr1);
    assert(roaring_bitmap_equals(r1, r1f));  // what we recover is equal
    roaring_bitmap_free(r1f);

    // we can go from arrays to bitmaps from "offset" by "limit"
    size_t offset = 100;
    size_t limit = 1000;
    uint32_t *arr3 = (uint32_t *)malloc(limit * sizeof(uint32_t));
    assert(arr3 != NULL);
    roaring_bitmap_range_uint32_array(r1, offset, limit, arr3);
    free(arr3);

    // we can copy and compare bitmaps
    roaring_bitmap_t *z = roaring_bitmap_copy(r3);
    assert(roaring_bitmap_equals(r3, z));  // what we recover is equal
    roaring_bitmap_free(z);

    // we can compute union two-by-two
    roaring_bitmap_t *r1_2_3 = roaring_bitmap_or(r1, r2);
    roaring_bitmap_or_inplace(r1_2_3, r3);

    // we can compute a big union
    const roaring_bitmap_t *allmybitmaps[] = {r1, r2, r3};
    roaring_bitmap_t *bigunion = roaring_bitmap_or_many(3, allmybitmaps);
    assert(
        roaring_bitmap_equals(r1_2_3, bigunion));  // what we recover is equal
    // can also do the big union with a heap
    roaring_bitmap_t *bigunionheap =
        roaring_bitmap_or_many_heap(3, allmybitmaps);
    assert(roaring_bitmap_equals(r1_2_3, bigunionheap));

    roaring_bitmap_free(r1_2_3);
    roaring_bitmap_free(bigunion);
    roaring_bitmap_free(bigunionheap);

    // we can compute intersection two-by-two
    roaring_bitmap_t *i1_2 = roaring_bitmap_and(r1, r2);
    roaring_bitmap_free(i1_2);

    // we can write a bitmap to a pointer and recover it later
    uint32_t expectedsize = roaring_bitmap_portable_size_in_bytes(r1);
    char *serializedbytes = malloc(expectedsize);
    roaring_bitmap_portable_serialize(r1, serializedbytes);
    roaring_bitmap_t *t = roaring_bitmap_portable_deserialize(serializedbytes);
    assert(roaring_bitmap_equals(r1, t));  // what we recover is equal
    roaring_bitmap_free(t);
    // we can also check whether there is a bitmap at a memory location without
    // reading it
    size_t sizeofbitmap =
        roaring_bitmap_portable_deserialize_size(serializedbytes, expectedsize);
    assert(sizeofbitmap ==
           expectedsize);  // sizeofbitmap would be zero if no bitmap were found
    // we can also read the bitmap "safely" by specifying a byte size limit:
    t = roaring_bitmap_portable_deserialize_safe(serializedbytes, expectedsize);
    assert(roaring_bitmap_equals(r1, t));  // what we recover is equal
    roaring_bitmap_free(t);

    free(serializedbytes);

    // we can iterate over all values using custom functions
    uint32_t counter = 0;
    roaring_iterate(r1, roaring_iterator_sumall, &counter);

    // we can also create iterator structs
    counter = 0;
    roaring_uint32_iterator_t *i = roaring_create_iterator(r1);
    while (i->has_value) {
        counter++;  // could use    i->current_value
        roaring_advance_uint32_iterator(i);
    }
    // you can skip over values and move the iterator with
    // roaring_move_uint32_iterator_equalorlarger(i,someintvalue)

    roaring_free_uint32_iterator(i);
    // roaring_bitmap_get_cardinality(r1) == counter

    // for greater speed, you can iterate over the data in bulk
    i = roaring_create_iterator(r1);
    uint32_t buffer[256];
    while (1) {
        uint32_t ret = roaring_read_uint32_iterator(i, buffer, 256);
        for (uint32_t j = 0; j < ret; j++) {
            counter += buffer[j];
        }
        if (ret < 256) {
            break;
        }
    }
    roaring_free_uint32_iterator(i);

    roaring_bitmap_free(r1);
    roaring_bitmap_free(r2);
    roaring_bitmap_free(r3);
    return EXIT_SUCCESS;
}

Example (C++)

#include <iostream>

#include "roaring.hh"

using namespace roaring;

int main() {
    Roaring r1;
    for (uint32_t i = 100; i < 1000; i++) {
        r1.add(i);
    }

    // check whether a value is contained
    assert(r1.contains(500));

    // compute how many bits there are:
    uint32_t cardinality = r1.cardinality();

    // if your bitmaps have long runs, you can compress them by calling
    // run_optimize
    uint32_t size = r1.getSizeInBytes();
    r1.runOptimize();

    // you can enable "copy-on-write" for fast and shallow copies
    r1.setCopyOnWrite(true);

    uint32_t compact_size = r1.getSizeInBytes();
    std::cout << "size before run optimize " << size << " bytes, and after "
              << compact_size << " bytes." << std::endl;

    // create a new bitmap with varargs
    Roaring r2 = Roaring::bitmapOf(5, 1, 2, 3, 5, 6);

    r2.printf();
    printf("\n");

    // we can also create a bitmap from a pointer to 32-bit integers
    const uint32_t values[] = {2, 3, 4};
    Roaring r3(3, values);

    // we can also go in reverse and go from arrays to bitmaps
    uint64_t card1 = r1.cardinality();
    uint32_t *arr1 = new uint32_t[card1];
    r1.toUint32Array(arr1);
    Roaring r1f(card1, arr1);
    delete[] arr1;

    // bitmaps shall be equal
    assert(r1 == r1f);

    // we can copy and compare bitmaps
    Roaring z(r3);
    assert(r3 == z);

    // we can compute union two-by-two
    Roaring r1_2_3 = r1 | r2;
    r1_2_3 |= r3;

    // we can compute a big union
    const Roaring *allmybitmaps[] = {&r1, &r2, &r3};
    Roaring bigunion = Roaring::fastunion(3, allmybitmaps);
    assert(r1_2_3 == bigunion);

    // we can compute intersection two-by-two
    Roaring i1_2 = r1 & r2;

    // we can write a bitmap to a pointer and recover it later
    uint32_t expectedsize = r1.getSizeInBytes();
    char *serializedbytes = new char[expectedsize];
    r1.write(serializedbytes);
    Roaring t = Roaring::read(serializedbytes);
    assert(r1 == t);
    delete[] serializedbytes;

    // we can iterate over all values using custom functions
    uint32_t counter = 0;
    r1.iterate(
        [](uint32_t value, void *param) {
            *(uint32_t *)param += value;
            return true;
        },
        &counter);

    // we can also iterate the C++ way
    counter = 0;
    for (Roaring::const_iterator i = t.begin(); i != t.end(); i++) {
        ++counter;
    }
    // counter == t.cardinality()

    // we can move iterators to skip values
    const uint32_t manyvalues[] = {2, 3, 4, 7, 8};
    Roaring rogue(5, manyvalues);
    Roaring::const_iterator j = rogue.begin();
    j.equalorlarger(4);  // *j == 4
    return EXIT_SUCCESS;
}

Building with cmake (Linux and macOS, Visual Studio users should see below)

CRoaring follows the standard cmake workflow. Starting from the root directory of the project (CRoaring), you can do:

mkdir -p build
cd build
cmake ..
make
# follow by 'make test' if you want to test.
# you can also type 'make install' to install the library on your system
# C header files typically get installed to /usr/local/include/roaring
# whereas C++ header files get installed to /usr/local/include/roaring

(You can replace the build directory with any other directory name.) You can generate a static library by adding -DROARING_BUILD_STATIC=ON to the command line. By default all tests are built on all platforms, to skip building and running tests add -DENABLE_ROARING_TESTS=OFF to the command line.

As with all cmake projects, you can specify the compilers you wish to use by adding (for example) -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ to the cmake command line.

If you wish to build an x64 version while disabling AVX2 and BMI2 support at the expense of performance, you can do the following :

mkdir -p buildnoavx
cd buildnoavx
cmake -DROARING_DISABLE_AVX=ON ..
make

The reverse is also possible. Some compilers may not enable AVX2 support, but you can force it in the following manner:

mkdir -p buildwithavx
cd buildwithavx
cmake -DFORCE_AVX=ON ..
make

If you have x64 hardware, but you wish to disable all x64-specific optimizations (including AVX), then you can do the following...

mkdir -p buildnox64
cd buildnoavx
cmake -DROARING_DISABLE_X64=ON ..
make

We tell the compiler to target the architecture of the build machine by using the march=native flag. This give the compiler the freedom to use instructions that your CPU support, but can be dangerous if you are going to use the built binaries on different machines. For example, you could get a SIGILL crash if you run the code on an older machine which does not have some of the instructions (e.g. POPCOUNT). There are two ways to deal with this:

First, you can disable this feature altogether by specifying -DROARING_DISABLE_NATIVE=OFF:

mkdir -p buildnonative
cd buildnoavx
cmake -DROARING_DISABLE_NATIVE=ON ..
make

Second, you can specify the architecture by specifying -DROARING_ARCH=arch. For example, if you have many servers but the oldest server is running the Intel westmere architecture, you can specify -DROARING_ARCH=westmere. You can find out the list of valid architecture values by typing man gcc. If -DROARING_DISABLE_NATIVE=on is specified, then this option has no effect.

mkdir -p build_westmere
cd build_westmere
cmake -DROARING_ARCH=westmere ..
make

For a debug release, starting from the root directory of the project (CRoaring), try

mkdir -p debug
cd debug
cmake -DCMAKE_BUILD_TYPE=Debug -DROARING_SANITIZE=ON ..
make

(Again, you can use the -DROARING_DISABLE_AVX=ON flag if you need it.)

(Of course you can replace the debug directory with any other directory name.)

To run unit tests (you must first run make):

make test

The detailed output of the tests can be found in Testing/Temporary/LastTest.log.

To run real-data benchmark

./real_bitmaps_benchmark ../benchmarks/realdata/census1881

where you must adjust the path "../benchmarks/realdata/census1881" so that it points to one of the directories in the benchmarks/realdata directory.

To check that your code abides by the style convention (make sure that clang-format is installed):

./tools/clang-format-check.sh

To reformat your code according to the style convention (make sure that clang-format is installed):

./tools/clang-format.sh

Building (Visual Studio under Windows)

We are assuming that you have a common Windows PC with at least Visual Studio 2015, and an x64 processor.

To build with at least Visual Studio 2015 from the command line:

  • Grab the CRoaring code from GitHub, e.g., by cloning it using GitHub Desktop.
  • Install CMake. When you install it, make sure to ask that cmake be made available from the command line.
  • Create a subdirectory within CRoaring, such as VisualStudio.
  • Using a shell, go to this newly created directory. For example, within GitHub Desktop, you can right-click on  CRoaring in your GitHub repository list, and select Open in Git Shell, then type cd VisualStudio in the newly created shell.
  • Type cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. in the shell while in the VisualStudio repository. (Alternatively, if you want to build a static library, you may use the command line cmake -DCMAKE_GENERATOR_PLATFORM=x64 -DROARING_BUILD_STATIC=ON ...)
  • This last command created a Visual Studio solution file in the newly created directory (e.g., RoaringBitmap.sln). Open this file in Visual Studio. You should now be able to build the project and run the tests. For example, in the Solution Explorer window (available from the View menu), right-click ALL_BUILD and select Build. To test the code, still in the Solution Explorer window, select RUN_TESTS and select Build.

To build with at least Visual Studio 2017 directly in the IDE:

  • Grab the CRoaring code from GitHub, e.g., by cloning it using GitHub Desktop.
  • Select the Visual C++ tools for CMake optional component when installing the C++ Development Workload within Visual Studio.
  • Within Visual Studio use File > Open > Folder... to open the CRoaring folder.
  • Right click on CMakeLists.txt in the parent directory within Solution Explorer and select Build to build the project.
  • For testing, in the Standard toolbar, drop the Select Startup Item... menu and choose one of the tests. Run the test by pressing the button to the left of the dropdown.

We have optimizations specific to AVX2 in the code, and they are turned only if the __AVX2__ macro is defined. In turn, these optimizations should only be enabled if you know that your target machines will support AVX2. Given that all recent Intel and AMD processors support AVX2, you may want to make this assumption. Thankfully, Visual Studio does define the __AVX2__ macro whenever the /arch:AVX2 compiler option is set. Unfortunately, this option might not be set by default. Thankfully, you can enable it with CMake by adding the -DFORCE_AVX=ON flag (e.g., type cmake -DFORCE_AVX=ON -DCMAKE_GENERATOR_PLATFORM=x64 .. instead of cmake -DCMAKE_GENERATOR_PLATFORM=x64 ..). If you are building directly in the IDE (with at least Visual Studio 2017 and the Visual C++ tools for CMake component), then right click on CMakeLists.txt and select "Change CMake Settings". This opens a JSON file called CMakeSettings.json. This file allows you to add CMake flags by editing the "cmakeCommandArgs" keys. E.g., you can modify the lines that read "cmakeCommandArgs" : "" so that they become "cmakeCommandArgs" : "-DFORCE_AVX=ON". The relevant part of the JSON file might look at follows:

  {
    "name": "x64-Debug",
    "generator": "Visual Studio 15 2017 Win64",
    "configurationType": "Debug",
    "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
    "cmakeCommandArgs": "-DFORCE_AVX=ON",
    "buildCommandArgs": "-m -v:minimal"
  },
  {
    "name": "x64-Release",
    "generator": "Visual Studio 15 2017 Win64",
    "configurationType" : "Release",
    "buildRoot":  "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
    "cmakeCommandArgs":  "-DFORCE_AVX=ON",
    "buildCommandArgs": "-m -v:minimal"
   }

After this modification, the output of CMake should include a line such as this one:

   CMAKE_C_FLAGS:   /arch:AVX2  -Wall

You must understand that this implies that the produced binaries will not run on hardware that does not support AVX2. However, you might get better performance.

We have additionnal optimizations that use inline assembly. However, Visual Studio does not support inline assembly so you cannot benefit from these optimizations under Visual Studio.

Usage (Using conan)

You can install the library using the conan package manager:

$ echo -e "[requires]\nroaring/0.2.66" > conanfile.txt
$ conan install .

Usage (Using vcpkg on Windows, Linux and macOS)

vcpkg users on Windows, Linux and macOS can download and install roaring with one single command from their favorite shell.

On Linux and macOS:

$ ./vcpkg install roaring

will build and install roaring as a static library.

On Windows (64-bit):

.\vcpkg.exe install roaring:x64-windows

will build and install roaring as a shared library.

.\vcpkg.exe install roaring:x64-windows-static  

will build and install roaring as a static library.

These commands will also print out instructions on how to use the library from MSBuild or CMake-based projects.

If you find the version of roaring shipped with vcpkg is out-of-date, feel free to report it to vcpkg community either by submiting an issue or by creating a PR.

AVX2-related throttling

Our AVX2 code does not use floating-point numbers or multiplications, so it is not subject to turbo frequency throttling on many-core Intel processors.

Thread safety

Like, for example, STL containers or Java's default data structures, the CRoaring library has no built-in thread support. Thus whenever you modify a bitmap in one thread, it is unsafe to query it in others. It is safe however to query bitmaps (without modifying them) from several distinct threads, as long as you do not use the copy-on-write attribute. For example, you can safely copy a bitmap and use both copies in concurrently. One should probably avoid the use of the copy-on-write attribute in a threaded environment.

How to best aggregate bitmaps?

Suppose you want to compute the union (OR) of many bitmaps. How do you proceed? There are many different strategies.

You can use roaring_bitmap_or_many(bitmapcount, bitmaps) or roaring_bitmap_or_many_heap(bitmapcount, bitmaps) or you may even roll your own aggregation:

roaring_bitmap_t *answer  = roaring_bitmap_copy(bitmaps[0]);
for (size_t i = 1; i < bitmapcount; i++) {
  roaring_bitmap_or_inplace(answer, bitmaps[i]);
}

All of them will work but they have different performance characteristics. The roaring_bitmap_or_many_heap should probably only be used if, after benchmarking, you find that it is faster by a good margin: it uses more memory.

The roaring_bitmap_or_many is meant as a good default. It works by trying to delay work as much as possible. However, because it delays computations, it also does not optimize the format as the computation runs. It might thus fail to see some useful pattern in the data such as long consecutive values.

The approach based on repeated calls to roaring_bitmap_or_inplace is also fine, and might even be faster in some cases. You can expect it to be faster if, after a few calls, you get long sequences of consecutive values in the answer. That is, if the final answer is all integers in the range [0,1000000), and this is apparent quickly, then the later roaring_bitmap_or_inplace will be very fast.

You should benchmark these alternatives on your own data to decide what is best.

Python Wrapper

Tom Cornebize wrote a Python wrapper available at https://github.com/Ezibenroc/PyRoaringBitMap Installing it is as easy as typing...

pip install pyroaring

JavaScript Wrapper

Salvatore Previti wrote a Node/JavaScript wrapper available at https://github.com/SalvatorePreviti/roaring-node Installing it is as easy as typing...

npm install roaring

Swift Wrapper

Jérémie Piotte wrote a Swift wrapper.

C# Wrapper

Brandon Smith wrote a C# wrapper available at https://github.com/RogueException/CRoaring.Net (works for Windows and Linux under x64 processors)

Go (golang) Wrapper

There is a Go (golang) wrapper available at https://github.com/RoaringBitmap/gocroaring

Rust Wrapper

Saulius Grigaliunas wrote a Rust wrapper available at https://github.com/saulius/croaring-rs

D Wrapper

Yuce Tekol wrote a D wrapper available at https://github.com/yuce/droaring

Redis Module

Antonio Guilherme Ferreira Viggiano wrote a Redis Module available at https://github.com/aviggiano/redis-roaring

Mailing list/discussion group

https://groups.google.com/forum/#!forum/roaring-bitmaps

References about Roaring

  • Daniel Lemire, Owen Kaser, Nathan Kurz, Luca Deri, Chris O'Hara, François Saint-Jacques, Gregory Ssi-Yan-Kai, Roaring Bitmaps: Implementation of an Optimized Software Library, Software: Practice and Experience (to appear) arXiv:1709.07821
  • Samy Chambi, Daniel Lemire, Owen Kaser, Robert Godin, Better bitmap performance with Roaring bitmaps, Software: Practice and Experience Volume 46, Issue 5, pages 709–719, May 2016 http://arxiv.org/abs/1402.6407 This paper used data from http://lemire.me/data/realroaring2014.html
  • Daniel Lemire, Gregory Ssi-Yan-Kai, Owen Kaser, Consistently faster and smaller compressed bitmaps with Roaring, Software: Practice and Experience (accepted in 2016, to appear) http://arxiv.org/abs/1603.06549
  • Samy Chambi, Daniel Lemire, Robert Godin, Kamel Boukhalfa, Charles Allen, Fangjin Yang, Optimizing Druid with Roaring bitmaps, IDEAS 2016, 2016. http://r-libre.teluq.ca/950/
Comments
  • Custom memory management

    Custom memory management

    The first change is the addition of a roaring_options_t struct that can be passed in as a pointer to new variants of most of the existing externals.

    Some examples...

    roaring_bitmap_t *roaring_bitmap_create(void);
    roaring_bitmap_t *roaring_bitmap_create_with_opts(roaring_options_t *options);
    
    roaring_bitmap_t *roaring_bitmap_and(const roaring_bitmap_t *x1,
                                         const roaring_bitmap_t *x2);
    roaring_bitmap_t *roaring_bitmap_and_with_opts(const roaring_bitmap_t *x1,
                                                   const roaring_bitmap_t *x2,
                                                   roaring_options_t *options);
    

    The roaring_options_t struct is intended to be an extendable struct that is accessible and common at all levels of the bitmap. When provided, memory is allocated and held by the roaring_bitmap_t instance, which owns the lifetime of this struct. A pointer to this memory is passed down to the roaring_array_t, and all the containers therein. This option struct is entirely optional and can be set to NULL.

    The design of this change was intended to have the least external impact possible, meaning that for the most part, tests of the externals have remained unchanged. Changes were required on some of the lower-level test cases, for example, the ones that created and manipulated containers directly.

    The roaring_options_t struct is defined in include/roaring/options.h as...

    struct roaring_options_s {
        roaring_memory_t* memory;
    };
    

    Within roaring_options_t there is another new struct, roaring_memory_t. This contains function pointers to custom memory management functions and a void pointer that can be used by the caller to pass down additional inputs to these functions.

    The roaring_memory_t struct is defined in include/roaring/memory.h as...

    struct roaring_memory_s {
        p_roaring_malloc malloc;
        p_roaring_realloc realloc;
        p_roaring_calloc calloc;
        p_roaring_free free;
        p_roaring_aligned_malloc aligned_malloc;
        p_roaring_aligned_free aligned_free;
        void* payload;
    };
    

    Finally, each call to the built-in memory management function that existed previously in the code has been replaced with shims that consume an option struct pointer. For example...

    void* roaring_malloc(roaring_options_t* options, size_t n) {
        if (options != NULL && options->memory != NULL &&
            options->memory->malloc != NULL) {
            return options->memory->malloc(n, options->memory->payload);
        }
        return malloc(n);
    }
    

    If the options, memory, and function pointer are all non-null, it will use the user-provided memory function. Otherwise, it will use the built-ins as before. Examples of how this is employed can be found in tests/memory_unit.cpp.

    This code is far from perfect, but it satisfies the requirements for my team's project. It has survived the reversion of mass reformatting and a fairly significant merge up to master as we were using an older release tag for development. I hope that this will provide a solid starting point for this new feature, and am looking forward to working with this community in its development.

    opened by olanmatt-ibm 59
  • Compilation on windows?

    Compilation on windows?

    Are there any plans to support windows 64bit, preferably with the visual studio compiler or else mingw/cygwin?

    I got it to compile and run on VS2015 (unit test still fail) but this already required quite some changes to the code.

    help wanted 
    opened by mrboojum 56
  • Implement a dispatched model for compilation of the CPU capabilities

    Implement a dispatched model for compilation of the CPU capabilities

    Since we have a range of optimizations currently available and likely to add more/improve over time, the complexity of building with the appropriate configuration can be tricky.

    Ideally, we would have a dispatching library that is able to select our optimal implementation at run time based on the CPU feature set. Most libraries I’ve seen that offer dispatched models use environment variables to disable or adjust things on the fly.

    For GCC we could use https://gcc.gnu.org/wiki/FunctionMultiVersioning, MSVC is a bit more complicated and it may be inevitable that there will be some function pointers to glue things together, I’ve started with some intrinsic routines to get going also and will be evaluating some options in keeping with pure C (no templates). It'd be nice to have a simple pattern that worked for all compiler/build targets.

    help wanted 
    opened by K2 36
  • Embedded C object inside C++ object

    Embedded C object inside C++ object

    changed the pointer to a CRoaring object inside of the C++ class into the object itself, avoiding a malloc and free in the constructor/destructor, this makes little difference to the 32-bit C++ class but speeds up adds to the 64-bit class by a few percent, also did a few minor things

    Bug fix: C++ iterators now stop at max uint32_t instead of comparing equal to the end iterator at this point Performance: removed virtual keyword for C++ iterator class's destructor since it will cause most compilers to generate a vtable for each object, bloating it up (the lack of the keyword is safe in this case unless a user subclasses the iterator and that subclass is deleted through a pointer with the type of the base class) Feature: added a toString member function to the C++ classes which makes STL strings

    opened by ksajme 19
  • roaring_bitmap_run_optimize() issue

    roaring_bitmap_run_optimize() issue

    Hi Lemire,

    I confuse on function roaring_bitmap_run_optimize(). Could you please help to explain me?? I made a simple test (please see below code), then run in 2 contexts:

    1. Build and run below code normally.
    2. Comment function // roaring_bitmap_run_optimize(reg). Then build and run again

    While program is looping, i measure memory usage by command "pmap (pid_of_program)" I found that size of "reg" reduces much however total memory gotten from pmap is not changed.

    I think memory gotten from pmap should reduce after run optimize, is it correct?

    int main(int argc, char** argv) 
    {
        int i, k, n;
        roaring_bitmap_t *reg;
        uint32_t count;
    
        reg = roaring_bitmap_create();
        for (i=0; i<320000000; i++) {
            roaring_bitmap_add(reg, i);
        }
        count = roaring_bitmap_portable_size_in_bytes(reg);
        printf("size before optimize: %d\n", count);
        roaring_bitmap_run_optimize(reg);  // comment this function to run second test
        count = roaring_bitmap_portable_size_in_bytes(reg);
        printf("size after optimize: %d\n", count);
        while (1);
    }
    
    opened by ancuop 19
  • Introduce `roaring_bitmap_*_bulk` operations

    Introduce `roaring_bitmap_*_bulk` operations

    Add "bulk" operations, which use a context structure to keep track of the last accessed container, and info about it (idx, type, key). This can allow for more optimal performance when multiple items will be accessed in the same or nearby containers.

    roaring_bitmap_add_bulk is a generalization of roaring_bitmap_add. Additionally, use the new function in the implementation of roaring_bitmap_add_many and roaring_bitmap_of.

    roaring_bitmap_contains_bulk is a generalization of roaring_bitmap_contains.

    Add tests and benchmarks. Should replace #371.

    opened by Dr-Emann 18
  • Implemented copy-on-write (CoW) at the container level.

    Implemented copy-on-write (CoW) at the container level.

    This seems to pass our unit tests and it seems to generally help our performance without doing any harm.

    Basically, it helps the performance when you would otherwise have to clone containers needlessly. It is not just the copying, but also the memory usage, the memory allocation and so forth. How often this happens depends very much on the data. However, avoiding even just one container copy can maybe be worth it.

    To see how much it can help, here is the number of cycles per input value for successive unions in the census1881 data set.

    Before (no CoW): 1.24 After (with CoW): 0.49

    To my surprise, there is at least one instance where we can double the performance with CoW.

    It does, however, slightly increase the code complexity. Maybe surprisingly, however, it is not so difficult to implement. It is possible however that I introduced memory leaks and so forth. Thread safety might be diminished as well, maybe. I don't know.

    Before merging this with master, I'd like for at least on fresh pair of eyes to review it. Indeed, if we adopt this, then it will have long-term consequences regarding maintenance and future work.

    It is likely, also, that I have let bugs slip.

    c.c. @owenkaser @fsaintjacques

    help wanted new feature performance 
    opened by lemire 18
  • Faster contains operation in array containers

    Faster contains operation in array containers

    Here is the change you can check out: https://github.com/WojciechMula/CRoaring/commit/6541bc70757351e7cc61e78df339a89eabf071d8

    As the commit messages states, it's a mix of binary search and linear search. Whenever range in binary search becomes smaller than some (small) threshold, we use linear search on this range. My experiments show that for relative small tables linear search wins. You can take a look at my old article http://0x80.pl/articles/simd-search.html#binary-search-with-fallback-to-linear-search-new.

    Below are benchmarks from Skylake and my old Westmere CPU. On Skylake we get nearly 1.5 speedup, on Westmere -- 1.2.

    Original
    
    Skylake:  contains_test(B):  147.80 cycles per operation
    Westmere: contains_test(B):  128.83 cycles per operation
    
    Modified (threshold = 8 items)
    
    Skylake:  contains_test(B):  101.91 cycles per operation
    Westmere: contains_test(B):  105.50 cycles per operation
    
    Modified (threshold = 16 items)
    
    Skylake:  contains_test(B):   97.91 cycles per operation
    Westmere: contains_test(B):  104.34 cycles per operation
    
    opened by WojciechMula 17
  • Improve efficiency of outer map operations for Roaring64Map

    Improve efficiency of outer map operations for Roaring64Map

    Hello,

    The purpose of this PR is to slightly improve the efficiency of Roaring64Map in C++.

    As you know Roaring64Map contains an "outer" std::map, which maps the key's high bits to individual (32-bit) Roaring maps, which in turn handle the key's low bits. The problem is that many of the methods in Roaring64Map probe the outer map more times than necessary. This includes high-traffic items like add() and contains(), which probe twice when they only need to probe once.

    I've changed a variety of methods to do fewer probes. While I was here I also took the liberty to make a few changes:

    • In flip(), I added what I believe to be a missing call to setCopyOnWrite()
    • In operator &=, operator -=, and operator ^=, if the 32-bit Roaring entry becomes empty, I remove it from the outer map altogether, rather than leaving an empty Roaring in that slot. I believe this is preferable (?)
    • In shrinkToFit() I removed an instance of what I believe is undefined behavior. In the line roarings.erase(iter++) I believe it is theoretically possible for the increment to happen after the call to erase has finished (and therefore iter would be an invalid iterator at that point and you ought not try to increment it). EDIT: no, this can't happen with an overloaded operator, so, forget I mentioned it. (I would still prefer to keep my change because I feel it reads better).
    • In maximum() I changed the code to use forward iterators, but traversing in the reverse direction, rather than reverse iterators. The rationale is that map's reverse_iterator is significantly slower than its forward_iterator, because in reverse_iterator, the operator * and operator -> methods are not constant time because they both do a decrement operation on a temporary internal tree iterator. I can provide more detail if you're interested.

    The code passes the current test suite. I'm not sure if that's sufficient or if additional tests need to be written.

    opened by kosak 16
  • support customized memory hook

    support customized memory hook

    Hi guys, Found the discussion in #284 and this is a lightweight implementation of customized allocator. We try to use it in our project and it works. For general users, default allocator would be used. For other users, allocator could be defined.

    opened by DarrenJiang13 16
  • Implement shift operations

    Implement shift operations

    For #186 and #144. It's still a work in progress. It's close to finished but I still need to sort out some bugs in the bitset implementation and clean up the tests, which are currently a bit of a mess and don't really convey enough information on failure.

    UPDATE: ready for review.

    opened by Oppen 16
  • Fast/convenient masking operations

    Fast/convenient masking operations

    Currently one can perform in-place or, andnot and xor operations with a range parameter through the addRange, removeRange and flip methods. Range-based and can be simulated by two consecutive calls to removeRange:

    bitmap.removeRange(0, a);
    bitmap.removeRange(b + 1, bitmap.maximum() + 1);
    

    It would be more convenient to have a method family like, e.g., mask and maskClosed implementing the same functionality directly.

    It would also be helpful to have a family of methods for performing range-restricted updates, i.e. something like

    bitmap1.add(otherBitmap, rangeStart, rangeEnd);
    bitmap2.flip(otherBitmap, rangeStart, rangeEnd);
    bitmap3.andnot(otherBitmap, rangeStart, rangeEnd);
    

    whose semantics would be

    Roaring maskedOp;
    maskedOp.addRange(rangeStart, rangeEnd);
    maskedOp &= otherBitmap;
    
    bitmap1 |= maskedOp;
    bitmap2 ^= maskedOp;
    bitmap3 -= maskedOp;
    

    Specialized methods could probably be much faster and more memory-efficient than the mask-based solution above.

    opened by fbbdev 0
  • fastunion vs |= in a loop

    fastunion vs |= in a loop

    I have a std::vector of Roaring64Maps

    std::vector<roaring::Roaring64Map> results = // some process
    

    When I use fastunion (probably incorrectly):

        auto sharded_results = new const roaring::Roaring64Map*[results.size()];
        for (size_t i = 0; i < results.size(); ++i) {
            sharded_results[i] = &results.data()[i];
        }
    
        roaring::Roaring64Map combined = roaring::Roaring64Map::fastunion(results.size(), sharded_results);
    

    It takes almost 5 seconds to combine them. However when I just do:

        roaring::Roaring64Map combined;
          for(const auto& sharded : results) {
            combined |= sharded;
        } 
    

    It takes 2.8 seconds. In this case I only have 4 maps, and the combined carnality ends up just above 3 million. Am I doing something wrong or is this expected?

    opened by maxdemarzi 1
  • Constant-time cardinality?

    Constant-time cardinality?

    Is there any appetite for being able to provide cardinality in constant time, on both the 32-bit and 64-bit sides? As a customer of the library I feel like I've wanted this.

    Right now it's calculated on demand. In Roaring64Map, the method cardinality() does a full scan of the map every time, and even isFull() will do a lot of work if applied to a map with a large dense prefix of full 32-bit bitmaps. isStrictSubset() also does two cardinality() calls that are not, from an algorithmic standpoint, strictly necessary, so that's a performance drag. On the 32-bit side, it's not constant-time either, requiring an iteration over the containers and an inner iteration over the run containers if there are any.

    Providing constant-time cardinality seems possible but not necessarily "easy" so I wanted to check with you first.

    I see three approaches here and I wanted to ask your opinion:

    1. Change both the 32-bit side and 64-bit side to provide constant-time cardinality.
    2. Change only the 64-bit side. The 64 bit side would do its own accounting to track the total cardinality. I think this is tricky but perhaps possible.
    3. Don't track cardinality. Then I could at the very least rewrite isStrictSubset so it does a more clever subset calculation that doesn't require any calls to cardinality()
    opened by kosak 2
  • Add roaring_bitmap_memory_size_in_bytes(), with C++ interfaces

    Add roaring_bitmap_memory_size_in_bytes(), with C++ interfaces

    No one commented on issue #406 so I just created this. We definitely need this, but not sure if it's too specific a need for others.

    The new roaring_bitmap_memory_size_in_bytes() function returns the number of in-memory bytes currently used by this Roaring bitmap.

    Add getMemorySizeInBytes() methods to the C++ Roaring and Roaring64Map classes. Note that the Roaring64Map result is somewhat guesswork since we can't accurately compute the memory used by the STL std::map implementation.

    opened by madscientist 8
  • Any interest in a function return number of bytes of memory used by a bitmap?

    Any interest in a function return number of bytes of memory used by a bitmap?

    I had a need to calculate the number of bytes of memory used for a given bitmap, so I created a set of functions that will do this, and plumbed them through both the C and C++ interfaces.

    Is there any interest in having something like this in the codebase?

    /**
     * Return the number of bytes of memory used by the bitmap.
     */
    size_t roaring_bitmap_memory_size_in_bytes(const roaring_bitmap_t *r);
    
    opened by madscientist 0
  • [WIP] Add SSE and AVX-512 support

    [WIP] Add SSE and AVX-512 support

    For issue #391

    Instead of using croaring_avx2() to switch on and off all vectorizing optimizations, add croaring_sse42() and croaring_bmi2() to specify what support a funciton actually needs. This enables old CPUs to use at least some of the optimizations.

    [WIP] Add vectorized functions using AVX-512 instructions for better performance. [WIP] Add vectorized functions using old SSE instructions to enable old machines that don't support AVX to use vectorized instructions.

    opened by CharlesChen888 0
Releases(v0.8.0)
  • v0.8.0(Nov 17, 2022)

    What's Changed

    • Update flip-type operations of Roaring64Map by @kosak in https://github.com/RoaringBitmap/CRoaring/pull/402
    • Improve add-type operations by @kosak in https://github.com/RoaringBitmap/CRoaring/pull/397
    • Fix build: remove duplicate 'ensureRangePopulated()' by @kosak in https://github.com/RoaringBitmap/CRoaring/pull/411
    • Add CodeQL workflow for GitHub code scanning by @lgtm-com in https://github.com/RoaringBitmap/CRoaring/pull/403
    • Provide a more aggressive Roaring64Map::fastunion() implementation by @kosak in https://github.com/RoaringBitmap/CRoaring/pull/405
    • Let us guard the malloc.h include with a check for glibc. by @lemire in https://github.com/RoaringBitmap/CRoaring/pull/412
    • add support for initializer lists by @lemire in https://github.com/RoaringBitmap/CRoaring/pull/408

    Full Changelog: https://github.com/RoaringBitmap/CRoaring/compare/v0.7.3...v0.8.0

    Source code(tar.gz)
    Source code(zip)
    roaring.c(745.14 KB)
    roaring.h(37.63 KB)
    roaring.hh(95.92 KB)
  • v0.7.3(Nov 11, 2022)

    What's Changed

    • Unit test cleanups: change assert -> assert_true, a couple other small things by @kosak in https://github.com/RoaringBitmap/CRoaring/pull/396
    • Improve efficiency of outer map operations for Roaring64Map by @kosak in https://github.com/RoaringBitmap/CRoaring/pull/390
    • Use ISO 8601 UTC dates as amalgamation timestamps by @urdvr in https://github.com/RoaringBitmap/CRoaring/pull/401
    • Improve remove-type operations by @kosak in https://github.com/RoaringBitmap/CRoaring/pull/398
    • Improve the code readability of Roaring64Map::printf() and Roaring64Map::toString() by @kosak in https://github.com/RoaringBitmap/CRoaring/pull/399
    • RoaringMap64::select(): remove illegal pointer cast; throw exception on unreachable code path. by @kosak in https://github.com/RoaringBitmap/CRoaring/pull/400
    • Fix a bug in containsRange that triggered an assert by @olaky in https://github.com/RoaringBitmap/CRoaring/pull/404

    New Contributors

    • @kosak made their first contribution in https://github.com/RoaringBitmap/CRoaring/pull/396
    • @urdvr made their first contribution in https://github.com/RoaringBitmap/CRoaring/pull/401
    • @olaky made their first contribution in https://github.com/RoaringBitmap/CRoaring/pull/404

    Full Changelog: https://github.com/RoaringBitmap/CRoaring/compare/v0.7.2...v0.7.3

    Source code(tar.gz)
    Source code(zip)
    roaring.c(745.18 KB)
    roaring.h(37.63 KB)
    roaring.hh(82.43 KB)
  • v0.7.2(Nov 4, 2022)

  • v0.7.1(Sep 7, 2022)

    What's Changed

    • Use a single binary search for array contains_range by @Dr-Emann in https://github.com/RoaringBitmap/CRoaring/pull/385
    • Fix truncated MIT license text by @esproul in https://github.com/RoaringBitmap/CRoaring/pull/389
    • Fix link in Readme by @gregsadetsky in https://github.com/RoaringBitmap/CRoaring/pull/388
    • Add doublechecked::Roaring64Map + tests, fix issues found by it by @SLieve in https://github.com/RoaringBitmap/CRoaring/pull/387

    New Contributors

    • @esproul made their first contribution in https://github.com/RoaringBitmap/CRoaring/pull/389
    • @gregsadetsky made their first contribution in https://github.com/RoaringBitmap/CRoaring/pull/388

    Full Changelog: https://github.com/RoaringBitmap/CRoaring/compare/v0.7.0...v0.7.1

    Source code(tar.gz)
    Source code(zip)
    roaring.c(744.74 KB)
    roaring.h(37.64 KB)
    roaring.hh(72.39 KB)
  • v0.7.0(Aug 26, 2022)

    What's Changed

    • Fixes for clangcl by @lemire in https://github.com/RoaringBitmap/CRoaring/pull/375
    • We should not override cmake's default flags without a good reason. by @lemire in https://github.com/RoaringBitmap/CRoaring/pull/378
    • Misc cpp fixes by @Dr-Emann in https://github.com/RoaringBitmap/CRoaring/pull/376
    • Adds new tests for C++ flip and other minor fixes by @lemire in https://github.com/RoaringBitmap/CRoaring/pull/380
    • Verifies fix on issue 382 by @lemire in https://github.com/RoaringBitmap/CRoaring/pull/383
    • Add add/removeRange to Roaring and Roaring64Map by @SLieve in https://github.com/RoaringBitmap/CRoaring/pull/381
    • Roaring64Map::readSafe: Check against maxbytes to read the size of the map by @SLieve in https://github.com/RoaringBitmap/CRoaring/pull/384
    • Introduce roaring_bitmap_*_bulk operations by @Dr-Emann in https://github.com/RoaringBitmap/CRoaring/pull/363

    New Contributors

    • @SLieve made their first contribution in https://github.com/RoaringBitmap/CRoaring/pull/381

    Full Changelog: https://github.com/RoaringBitmap/CRoaring/compare/v0.6.0...v0.7.0

    Source code(tar.gz)
    Source code(zip)
    roaring.c(744.50 KB)
    roaring.h(37.64 KB)
    roaring.hh(72.24 KB)
  • v0.6.0(Jul 20, 2022)

  • v0.5.0(Apr 13, 2022)

  • v0.4.0(Oct 12, 2021)

  • v0.3.4(Aug 16, 2021)

  • v0.3.3(Jul 25, 2021)

Owner
Roaring bitmaps: A better compressed bitset
Roaring bitmaps are compressed bitmaps. They can be hundreds of times faster. (Picture credit: tambako)
Roaring bitmaps: A better compressed bitset
Compile and execute C "scripts" in one go!

c "There isn't much that's special about C. That's one of the reasons why it's fast." I love C for its raw speed (although it does have its drawbacks)

Ryan Jacobs 2k Dec 30, 2022
distributed builds for C, C++ and Objective C

distcc -- a free distributed C/C++ compiler system by Martin Pool Current Documents: https://distcc.github.io/ Formally http://distcc.org/ "pump" func

distcc 1.8k Dec 27, 2022
New generation entropy codecs : Finite State Entropy and Huff0

New Generation Entropy coders This library proposes two high speed entropy coders : Huff0, a Huffman codec designed for modern CPU, featuring OoO (Out

Yann Collet 1.1k Dec 26, 2022
Compression abstraction library and utilities

Squash - Compresion Abstraction Library

null 375 Dec 22, 2022
Multi-format archive and compression library

Welcome to libarchive! The libarchive project develops a portable, efficient C library that can read and write streaming archives in a variety of form

null 1.9k Dec 26, 2022
Easing the task of comparing code generated by cc65, vbcc, and 6502-gcc

6502 C compilers benchmark Easing the way to compare code generated by cc65, 6502-gcc, vbcc, and KickC. This repository contains scripts to: Compile t

Sylvain Gadrat 17 Sep 4, 2022
Secure ECC-based DID intersection in Go, Java and C.

SecureUnionID Secure ECC-based DID intersection. ABSTRACT This project is used to protect device ID using Elliptic Curve Cryptography algorithm. The d

Volcengine 20 Dec 27, 2022
nanoc is a tiny subset of C and a tiny compiler that targets 32-bit x86 machines.

nanoc is a tiny subset of C and a tiny compiler that targets 32-bit x86 machines. Tiny? The only types are: int (32-bit signed integer) char (8-

Ajay Tatachar 19 Nov 28, 2022
Smaller C is a simple and small single-pass C compiler

Smaller C is a simple and small single-pass C compiler, currently supporting most of the C language common between C89/ANSI C and C99 (minus some C89 and plus some C99 features).

Alexey Frunze 1.2k Jan 7, 2023
Microvm is a virtual machine and compiler

The aim of this project is to create a stack based language and virtual machine for microcontrollers. A mix of approaches is used. Separate memory is used for program and variable space (Harvard architecture). An interpreter, virtual machine and compiler are available. A demostration of the interpreter in action is presented below.

null 10 Aug 14, 2022
Pre-configured LLVM and ANTLR4 for C++

LLVM + ANTLR4 Starter Project Starter project for ANTLR4 and LLVM C++ project. Prerequisite LLVM 12 Java (for ANTLR4) git Install prerequisite librari

Nathanael Demacon 12 Aug 9, 2022
Aheui JIT compiler for PC and web

아희짓 개요 아희짓은 아희 언어를 위한 JIT (Just in Time) 컴파일러입니다. 어셈블러와 유틸 라이브러리외에 외부 라이브러리에 전혀 의존하지 않고 JIT을 바닥부터 구현합니다. 지원 환경 64비트 windows, mac, linux (x86 아키텍쳐) 웹어셈

Sunho Kim 28 Sep 23, 2022
Interpreter and miner for the LODA language written in C++

LODA Interpreter and Miner (C++) LODA is an assembly language, a computational model and a tool for mining integer sequences. You can use it to search

LODA Language 14 Dec 30, 2022
is a c++20 compile and runtime Struct Reflections header only library.

is a c++20 compile and runtime Struct Reflections header only library. It allows you to iterate over aggregate type's member variables.

RedSkittleFox 4 Apr 18, 2022
C++ python bytecode disassembler and decompiler

C++ python bytecode disassembler and decompiler

Michael Hansen 1.6k Jan 5, 2023
🌳 A compressed rank/select dictionary exploiting approximate linearity and repetitiveness.

The block-ε tree is a compressed rank/select dictionary that achieves new space-time trade-offs by exploiting the approximate linearity and the repeti

Giorgio Vinciguerra 10 Jun 5, 2022
A LLVM and Clang compiler toolchain built for kernel development

Cosmic-Clang Toolchain This is a LLVM and Clang compiler toolchain built for kernel development. Builds are always made from the latest LLVM sources r

Ǥђ๏ຮ₮⌁Ⲙครtє࿐ 0 Apr 12, 2022
UE4 SDF Importers / Generators for SVG and Bitmaps

RTMSDF UE4 SDF Importers / Generators for SVG and Bitmaps NOTE: This module is very much work in progress / preview and likely to change Uses MSDFGen

Richard Meredith 9 Sep 30, 2022
RdpCacheStitcher is a tool that supports forensic analysts in reconstructing useful images out of RDP cache bitmaps.

RdpCacheStitcher is a tool that supports forensic analysts in reconstructing useful images out of RDP cache bitmaps. Using raw RDP cache tile bitmaps extracted by tools like e.g. ANSSI's BMC-Tools as input, it provides a graphical user interface and several placement heuristics for stitching tiles together so that meaningful images or even full screenshots can be reconstructed.

Bundesamt für Sicherheit in der Informationstechnik 176 Jan 2, 2023
null 313 Dec 31, 2022