mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-10 16:24:45 -07:00
Update external c libs: SFMT & peglib (#6901)
This commit is contained in:
parent
a9003be30f
commit
74102aa1ec
3 changed files with 80 additions and 18 deletions
|
|
@ -60,7 +60,9 @@ inline static void swap(w128_t *array, int size);
|
|||
*/
|
||||
static const w128_t sse2_param_mask = {{SFMT_MSK1, SFMT_MSK2,
|
||||
SFMT_MSK3, SFMT_MSK4}};
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(__AVX2__) && (SFMT_SL1 >= 16) && !(SFMT_N & 1) && !(SFMT_POS1 & 1)
|
||||
#include "SFMT-avx256.h"
|
||||
#elif defined(_MSC_VER)
|
||||
#include "SFMT-sse2-msc.h"
|
||||
#else
|
||||
#include "SFMT-sse2.h"
|
||||
|
|
|
|||
|
|
@ -88,8 +88,13 @@ union W128_T {
|
|||
uint64_t u64[2];
|
||||
uint32x4_t si;
|
||||
};
|
||||
//#elif defined(HAVE_SSE2)
|
||||
#elif defined(HAVE_SSE2)
|
||||
#include <emmintrin.h>
|
||||
#if defined(__AVX2__)
|
||||
#include <immintrin.h>
|
||||
#else
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
/** 128-bit data structure */
|
||||
union W128_T {
|
||||
|
|
@ -112,8 +117,18 @@ typedef union W128_T w128_t;
|
|||
* SFMT internal state
|
||||
*/
|
||||
struct SFMT_T {
|
||||
#if defined(__AVX2__)
|
||||
union {
|
||||
w128_t state[SFMT_N];
|
||||
__m256i state_ymm[SFMT_N/2];
|
||||
#if defined(__AVX512VL__)
|
||||
__m512i state_zmm[SFMT_N/4];
|
||||
#endif
|
||||
};
|
||||
#else
|
||||
/** the 128-bit internal state array */
|
||||
w128_t state[SFMT_N];
|
||||
#endif
|
||||
/** index counter to the 32-bit internal state array */
|
||||
int idx;
|
||||
};
|
||||
|
|
@ -249,9 +264,9 @@ inline static double sfmt_genrand_real3(sfmt_t * sfmt)
|
|||
}
|
||||
|
||||
/**
|
||||
* converts an unsigned 32-bit integer to double on [0,1)
|
||||
* converts an unsigned 64-bit integer to double on [0,1)
|
||||
* with 53-bit resolution.
|
||||
* @param v 32-bit unsigned integer
|
||||
* @param v 64-bit unsigned integer
|
||||
* @return double on [0,1)-real-interval with 53-bit resolution.
|
||||
*/
|
||||
inline static double sfmt_to_res53(uint64_t v)
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#if !defined(__cplusplus) || __cplusplus < 201703L
|
||||
|
|
@ -505,7 +506,7 @@ inline constexpr unsigned int str2tag(std::string_view sv) {
|
|||
|
||||
namespace udl {
|
||||
|
||||
inline constexpr unsigned int operator""_(const char *s, size_t l) {
|
||||
inline constexpr unsigned int operator"" _(const char *s, size_t l) {
|
||||
return str2tag_core(s, l, 0);
|
||||
}
|
||||
|
||||
|
|
@ -2434,10 +2435,11 @@ struct ComputeFirstSet : public TraversalVisitor {
|
|||
|
||||
void visit(Sequence &ope) override {
|
||||
for (const auto &op : ope.opes_) {
|
||||
FirstSet element_fs;
|
||||
auto save = result_;
|
||||
result_ = FirstSet{};
|
||||
op->accept(*this);
|
||||
auto element_fs = result_;
|
||||
element_fs = result_;
|
||||
result_ = save;
|
||||
result_.chars |= element_fs.chars;
|
||||
if (element_fs.any_char) { result_.any_char = true; }
|
||||
|
|
@ -2526,10 +2528,22 @@ struct ComputeFirstSet : public TraversalVisitor {
|
|||
void visit(BackReference &) override { result_.any_char = true; }
|
||||
void visit(Cut &) override { result_.can_be_empty = true; }
|
||||
|
||||
// Per-rule cache shared across a SetupFirstSets traversal. Without it,
|
||||
// every alternative of every PrioritizedChoice re-walks referenced
|
||||
// rules — O(refs^depth) work for grammars with many cross-references.
|
||||
// Only cycle-free rule computations are cached; results computed under
|
||||
// a cycle (left recursion) would be incomplete and unsafe to reuse from
|
||||
// a different call context.
|
||||
using FirstSetCache = std::unordered_map<const Definition *, FirstSet>;
|
||||
|
||||
explicit ComputeFirstSet(FirstSetCache &cache) : cache_(cache) {}
|
||||
|
||||
FirstSet result_;
|
||||
|
||||
private:
|
||||
std::unordered_set<std::string> refs_;
|
||||
FirstSetCache &cache_;
|
||||
std::unordered_set<const Definition *> refs_;
|
||||
size_t cycle_count_ = 0;
|
||||
};
|
||||
|
||||
struct SetupFirstSets : public TraversalVisitor {
|
||||
|
|
@ -2542,7 +2556,7 @@ struct SetupFirstSets : public TraversalVisitor {
|
|||
ope.first_sets_.clear();
|
||||
ope.first_sets_.reserve(ope.opes_.size());
|
||||
for (const auto &op : ope.opes_) {
|
||||
ComputeFirstSet cfs;
|
||||
ComputeFirstSet cfs(first_set_cache_);
|
||||
op->accept(cfs);
|
||||
ope.first_sets_.push_back(cfs.result_);
|
||||
}
|
||||
|
|
@ -2559,7 +2573,8 @@ struct SetupFirstSets : public TraversalVisitor {
|
|||
void visit(Reference &ope) override;
|
||||
|
||||
private:
|
||||
std::unordered_set<std::string> refs_;
|
||||
ComputeFirstSet::FirstSetCache first_set_cache_;
|
||||
std::unordered_set<const Definition *> visited_rules_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -3806,20 +3821,50 @@ inline void ComputeFirstSet::visit(Reference &ope) {
|
|||
result_.any_char = true;
|
||||
return;
|
||||
}
|
||||
if (refs_.count(ope.name_)) { return; }
|
||||
refs_.insert(ope.name_);
|
||||
ope.rule_->accept(*this);
|
||||
if (!result_.first_rule && ope.rule_->is_token()) {
|
||||
result_.first_rule = ope.rule_;
|
||||
|
||||
auto it = cache_.find(ope.rule_);
|
||||
FirstSet computed;
|
||||
const FirstSet *rule_fs;
|
||||
if (it != cache_.end()) {
|
||||
rule_fs = &it->second;
|
||||
} else {
|
||||
if (!refs_.insert(ope.rule_).second) {
|
||||
cycle_count_++; // cycle / left recursion
|
||||
return;
|
||||
}
|
||||
auto save = std::exchange(result_, FirstSet{});
|
||||
auto saved_cycle_count = cycle_count_;
|
||||
ope.rule_->accept(*this);
|
||||
computed = std::move(result_);
|
||||
result_ = std::move(save);
|
||||
refs_.erase(ope.rule_);
|
||||
if (cycle_count_ == saved_cycle_count) {
|
||||
// Cycle-free: cached value is complete and safe to reuse.
|
||||
it = cache_.try_emplace(ope.rule_, std::move(computed)).first;
|
||||
rule_fs = &it->second;
|
||||
} else {
|
||||
// Cycle was hit during this rule's computation — its result may be
|
||||
// missing contributions from rules that were on the call stack.
|
||||
// Use the value here but do not cache it for other call contexts.
|
||||
rule_fs = &computed;
|
||||
}
|
||||
}
|
||||
|
||||
result_.merge(*rule_fs);
|
||||
if (!result_.first_literal) {
|
||||
result_.first_literal = rule_fs->first_literal;
|
||||
}
|
||||
if (!result_.first_rule) {
|
||||
result_.first_rule = rule_fs->first_rule
|
||||
? rule_fs->first_rule
|
||||
: (ope.rule_->is_token() ? ope.rule_ : nullptr);
|
||||
}
|
||||
refs_.erase(ope.name_);
|
||||
}
|
||||
|
||||
inline void SetupFirstSets::visit(Reference &ope) {
|
||||
if (!ope.rule_ || refs_.count(ope.name_)) { return; }
|
||||
refs_.insert(ope.name_);
|
||||
if (!ope.rule_) { return; }
|
||||
if (!visited_rules_.insert(ope.rule_).second) { return; }
|
||||
ope.rule_->accept(*this);
|
||||
refs_.erase(ope.name_);
|
||||
}
|
||||
|
||||
inline void SetupFirstSets::visit(Sequence &ope) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue