This source file includes following definitions.
- rng32
- random_int
- random_float
- visit
- lower_random
#include "Random.h"
#include "IROperator.h"
#include "IRMutator.h"
namespace Halide {
namespace Internal {
using std::vector;
using std::string;
namespace {
#define C0 576942909
#define C1 1121052041
#define C2 1040796640
Expr rng32(Expr x) {
internal_assert(x.type() == UInt(32));
if (const uint64_t *i = as_const_uint(x)) {
return make_const(UInt(32), ((C2 * (*i)) + C1) * (*i) + C0);
}
return (((C2 * x) + C1) * x) + C0;
}
}
Expr random_int(const vector<Expr> &e) {
internal_assert(e.size());
internal_assert(e[0].type() == Int(32) || e[0].type() == UInt(32));
Expr result = rng32(cast(UInt(32), e[0]));
for (size_t i = 1; i < e.size(); i++) {
internal_assert(e[i].type() == Int(32) || e[i].type() == UInt(32));
string name = unique_name('R');
const uint64_t *ir = as_const_uint(result);
const uint64_t *ie = as_const_uint(e[i]);
if (ir && ie) {
result = rng32(make_const(UInt(32), (*ir) + (*ie)));
} else {
result = Let::make(name, result + cast<uint32_t>(e[i]),
rng32(Variable::make(UInt(32), name)));
}
}
return result;
}
Expr random_float(const vector<Expr> &e) {
Expr result = random_int(e);
result = (127 << 23) | (cast<uint32_t>(result) >> 9);
return clamp(reinterpret(Float(32), result) - 1.0f, 0.0f, 1.0f);
}
class LowerRandom : public IRMutator {
using IRMutator::visit;
void visit(const Call *op) {
if (op->is_intrinsic(Call::random)) {
vector<Expr> args = op->args;
args.insert(args.end(), extra_args.begin(), extra_args.end());
if (op->type == Float(32)) {
expr = random_float(args);
} else if (op->type == Int(32)) {
expr = cast<int32_t>(random_int(args));
} else if (op->type == UInt(32)) {
expr = random_int(args);
} else {
internal_error << "The intrinsic random() returns an Int(32), UInt(32) or a Float(32).\n";
}
} else {
IRMutator::visit(op);
}
}
vector<Expr> extra_args;
public:
LowerRandom(const vector<string> &free_vars, int tag) {
extra_args.push_back(tag);
for (size_t i = 0; i < free_vars.size(); i++) {
internal_assert(!free_vars[i].empty());
extra_args.push_back(Variable::make(Int(32), free_vars[i]));
}
}
};
Expr lower_random(Expr e, const vector<string> &free_vars, int tag) {
LowerRandom r(free_vars, tag);
return r.mutate(e);
}
}
}