<commit_before>#include "Var.h"
#include "IR.h"
#include "IREquality.h"
#include "IROperator.h"
#include "IRVisitor.h"
#include "IRMutator.h"
#include "Reduction.h"
#include "Simplify.h"

namespace Halide {
namespace Internal {

namespace {

/* Split AND predicate into vector of ANDs. */
void split_predicate_helper(Expr pred, std::vector<Expr> &result) {
    if (const And *a = pred.as<And>()) {
        split_predicate_helper(a->a, result);
        split_predicate_helper(a->b, result);
    } else if (!is_one(pred)) {
        result.push_back(pred);
    }
}

void check(Expr pred, std::vector<Expr> &expected) {
    std::vector<Expr> result;
    split_predicate_helper(pred, result);
    bool is_equal = true;

    if (result.size() != expected.size()) {
        is_equal = false;
    } else {
        for (size_t i = 0; i < expected.size(); ++i) {
            if (!equal(simplify(result[i]), simplify(expected[i]))) {
                is_equal = false;
                break;
            }
        }
    }

    if (!is_equal) {
        std::cout << "Expect predicate " << pred << " to be split into:\n";
        for (const auto &e : expected) {
            std::cout << "  " << e << "\n";
        }
        std::cout << "Got:\n";
        for (const auto &e : result) {
            std::cout << "  " << e << "\n";
        }
        internal_error << "\n";
    }
}

}

void split_predicate_test() {
    Expr x = Var("x"), y = Var("y"), z = Var("z"), w = Var("w");

    {
        std::vector<Expr> expected;
        expected.push_back(z < 10);
        check(z < 10, expected);
    }

    {
        std::vector<Expr> expected;
        expected.push_back((x < y) || (x == 10));
        check((x < y) || (x == 10), expected);
    }

    {
        std::vector<Expr> expected;
        expected.push_back(x < y);
        expected.push_back(x == 10);
        check((x < y) && (x == 10), expected);
    }

    {
        std::vector<Expr> expected;
        expected.push_back(x < y);
        expected.push_back(x == 10);
        expected.push_back(y == z);
        check((x < y) && (x == 10) && (y == z), expected);
    }

    {
        std::vector<Expr> expected;
        expected.push_back((w == 1) || ((x == 10) && (y == z)));
        check((w == 1) || ((x == 10) && (y == z)), expected);
    }

    {
        std::vector<Expr> expected;
        expected.push_back(x < y);
        expected.push_back((w == 1) || ((x == 10) && (y == z)));
        check((x < y) && ((w == 1) || ((x == 10) && (y == z))), expected);
    }

    std::cout << "Split predicate test passed" << std::endl;
}

struct ReductionDomainContents {
    mutable RefCount ref_count;
    std::vector<ReductionVariable> domain;
    Expr predicate;
    bool frozen;

    ReductionDomainContents() : predicate(const_true()), frozen(false) {
    }

};

template<>
EXPORT RefCount &ref_count<Halide::Internal::ReductionDomainContents>(const ReductionDomainContents *p) {return p->ref_count;}

template<>
EXPORT void destroy<Halide::Internal::ReductionDomainContents>(const ReductionDomainContents *p) {delete p;}

ReductionDomain::ReductionDomain(const std::vector<ReductionVariable> &domain) :
    contents(new ReductionDomainContents) {
    contents.ptr->domain = domain;
}

const std::vector<ReductionVariable> &ReductionDomain::domain() const {
    return contents.ptr->domain;
}

void ReductionDomain::set_predicate(Expr p) {
    // The predicate can refer back to the RDom. We need to break
    // those cycles to prevent a leak.
    class DropSelfReferences : public IRMutator {
        using IRMutator::visit;

        void visit(const Variable *op) {
            if (op->reduction_domain.defined()) {
                user_assert(op->reduction_domain.same_as(domain))
                    << "An RDom's predicate may only refer to its own RVars, "
                    << " not the RVars of some other RDom. "
                    << "Cannot set the predicate to : " << predicate << "\n";
                expr = Variable::make(op->type, op->name);
            } else {
                expr = op;
            }
        }
    public:
        Expr predicate;
        const ReductionDomain &domain;
        DropSelfReferences(Expr p, const ReductionDomain &d) :
            predicate(p), domain(d) {}
    };

    contents.ptr->predicate = DropSelfReferences(p, *this).mutate(p);
}

void ReductionDomain::where(Expr predicate) {<commit_msg>Fix for msvc<commit_after>#include "Var.h"
#include "IR.h"
#include "IREquality.h"
#include "IROperator.h"
#include "IRVisitor.h"
#include "IRMutator.h"
#include "Reduction.h"
#include "Simplify.h"

namespace Halide {
namespace Internal {

namespace {

/* Split AND predicate into vector of ANDs. */
void split_predicate_helper(Expr pred, std::vector<Expr> &result) {
    if (const And *a = pred.as<And>()) {
        split_predicate_helper(a->a, result);
        split_predicate_helper(a->b, result);
    } else if (!is_one(pred)) {
        result.push_back(pred);
    }
}

void check(Expr pred, std::vector<Expr> &expected) {
    std::vector<Expr> result;
    split_predicate_helper(pred, result);
    bool is_equal = true;

    if (result.size() != expected.size()) {
        is_equal = false;
    } else {
        for (size_t i = 0; i < expected.size(); ++i) {
            if (!equal(simplify(result[i]), simplify(expected[i]))) {
                is_equal = false;
                break;
            }
        }
    }

    if (!is_equal) {
        std::cout << "Expect predicate " << pred << " to be split into:\n";
        for (const auto &e : expected) {
            std::cout << "  " << e << "\n";
        }
        std::cout << "Got:\n";
        for (const auto &e : result) {
            std::cout << "  " << e << "\n";
        }
        internal_error << "\n";
    }
}

}

void split_predicate_test() {
    Expr x = Var("x"), y = Var("y"), z = Var("z"), w = Var("w");

    {
        std::vector<Expr> expected;
        expected.push_back(z < 10);
        check(z < 10, expected);
    }

    {
        std::vector<Expr> expected;
        expected.push_back((x < y) || (x == 10));
        check((x < y) || (x == 10), expected);
    }

    {
        std::vector<Expr> expected;
        expected.push_back(x < y);
        expected.push_back(x == 10);
        check((x < y) && (x == 10), expected);
    }

    {
        std::vector<Expr> expected;
        expected.push_back(x < y);
        expected.push_back(x == 10);
        expected.push_back(y == z);
        check((x < y) && (x == 10) && (y == z), expected);
    }

    {
        std::vector<Expr> expected;
        expected.push_back((w == 1) || ((x == 10) && (y == z)));
        check((w == 1) || ((x == 10) && (y == z)), expected);
    }

    {
        std::vector<Expr> expected;
        expected.push_back(x < y);
        expected.push_back((w == 1) || ((x == 10) && (y == z)));
        check((x < y) && ((w == 1) || ((x == 10) && (y == z))), expected);
    }

    std::cout << "Split predicate test passed" << std::endl;
}

struct ReductionDomainContents {
    mutable RefCount ref_count;
    std::vector<ReductionVariable> domain;
    Expr predicate;
    bool frozen;

    ReductionDomainContents() : predicate(const_true()), frozen(false) {
    }

};

template<>
EXPORT RefCount &ref_count<Halide::Internal::ReductionDomainContents>(const ReductionDomainContents *p) {return p->ref_count;}

template<>
EXPORT void destroy<Halide::Internal::ReductionDomainContents>(const ReductionDomainContents *p) {delete p;}

ReductionDomain::ReductionDomain(const std::vector<ReductionVariable> &domain) :
    contents(new ReductionDomainContents) {
    contents.ptr->domain = domain;
}

const std::vector<ReductionVariable> &ReductionDomain::domain() const {
    return contents.ptr->domain;
}

namespace {
class DropSelfReferences : public IRMutator {
    using IRMutator::visit;

    void visit(const Variable *op) {
        if (op->reduction_domain.defined()) {
            user_assert(op->reduction_domain.same_as(domain))
                << "An RDom's predicate may only refer to its own RVars, "
                << " not the RVars of some other RDom. "
                << "Cannot set the predicate to : " << predicate << "\n";
            expr = Variable::make(op->type, op->name);
        } else {
            expr = op;
        }
    }
public:
    Expr predicate;
    const ReductionDomain &domain;
    DropSelfReferences(Expr p, const ReductionDomain &d) :
        predicate(p), domain(d) {}
};
}

void ReductionDomain::set_predicate(Expr p) {
    // The predicate can refer back to the RDom. We need to break
    // those cycles to prevent a leak.
    contents.ptr->predicate = DropSelfReferences(p, *this).mutate(p);
}

void ReductionDomain::where(Expr predicate) {
{'fraction_non_alphanumeric': 0.16271341812764983, 'fraction_numerical': 0.006646041022115274, 'mean_word_length': 2.47175815433572, 'pattern_counts': {'":': 0, '<': 131, '<?xml version=': 0, '>': 57, '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': '7345712', 'n_tokens_mistral': 2902, 'n_tokens_neox': 2725, 'n_words': 661}