<commit_before>#ifndef SINGLEBITVECTORPOINTSTOSET_H
#define SINGLEBITVECTORPOINTSTOSET_H

#include "dg/PointerAnalysis/Pointer.h"
#include "dg/ADT/Bitvector.h"
#include "LookupTable.h"

#include <map>
#include <vector>
#include <cassert>

namespace dg {
namespace pta {

class PSNode;

class PointerIdPointsToSet {
    static PointerIDLookupTable lookupTable;

    using PointersT = ADT::SparseBitvectorHashImpl;
    PointersT pointers;

    //if the pointer doesn't have ID, it's assigned one
    size_t getPointerID(const Pointer& ptr) const {
        return lookupTable.getOrCreate(ptr);
    }

    const Pointer& getPointer(size_t id) const {
        return lookupTable.get(id);
    }

    bool addWithUnknownOffset(PSNode* node) {
        removeAny(node);
        return !pointers.set(getPointerID({node, Offset::UNKNOWN}));
    }

public:
    PointerIdPointsToSet() = default;
    explicit PointerIdPointsToSet(const std::initializer_list<Pointer>& elems) { add(elems); }

    bool add(PSNode *target, Offset off) {
        return add(Pointer(target,off));
    }

    bool add(const Pointer& ptr) {
        if(has({ptr.target, Offset::UNKNOWN})) {
            return false;
        }
        if(ptr.offset.isUnknown()) {
            return addWithUnknownOffset(ptr.target);
        }
        return !pointers.set(getPointerID(ptr));
    }

    template <typename ContainerTy><commit_msg>ID PTSet: remove concrete offset only when when we have no ? offset<commit_after>#ifndef SINGLEBITVECTORPOINTSTOSET_H
#define SINGLEBITVECTORPOINTSTOSET_H

#include "dg/PointerAnalysis/Pointer.h"
#include "dg/ADT/Bitvector.h"
#include "LookupTable.h"

#include <map>
#include <vector>
#include <cassert>

namespace dg {
namespace pta {

class PSNode;

class PointerIdPointsToSet {
    static PointerIDLookupTable lookupTable;

    using PointersT = ADT::SparseBitvectorHashImpl;
    PointersT pointers;

    //if the pointer doesn't have ID, it's assigned one
    size_t getPointerID(const Pointer& ptr) const {
        return lookupTable.getOrCreate(ptr);
    }

    const Pointer& getPointer(size_t id) const {
        return lookupTable.get(id);
    }

    bool addWithUnknownOffset(PSNode* node) {
        auto ptrid = getPointerID({node, Offset::UNKNOWN});
        if (!pointers.get(ptrid)) {
            removeAny(node);
            return !pointers.set(ptrid);
        }
        return false; // we already had it
    }

public:
    PointerIdPointsToSet() = default;
    explicit PointerIdPointsToSet(const std::initializer_list<Pointer>& elems) { add(elems); }

    bool add(PSNode *target, Offset off) {
        return add(Pointer(target,off));
    }

    bool add(const Pointer& ptr) {
        if(has({ptr.target, Offset::UNKNOWN})) {
            return false;
        }
        if(ptr.offset.isUnknown()) {
            return addWithUnknownOffset(ptr.target);
        }
        return !pointers.set(getPointerID(ptr));
    }

    template <typename ContainerTy>
{'fraction_non_alphanumeric': 0.10691399662731872, 'fraction_numerical': 0.0, 'mean_word_length': 3.231098430813124, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1461896', 'n_tokens_mistral': 940, 'n_tokens_neox': 919, 'n_words': 207}