struct Value {
v: vec4f,
}
fn op_neg(lhs: Value) -> Value {
return Value(-lhs.v);
}
fn op_abs(lhs: Value) -> Value {
if lhs.v.w < 0.0 {
return Value(-lhs.v);
} else {
return lhs;
}
}
fn op_recip(lhs: Value) -> Value {
let v2 = -lhs.v.w * lhs.v.w;
return Value(vec4f(lhs.v.xyz / v2, 1.0 / lhs.v.w));
}
fn op_sqrt(lhs: Value) -> Value {
let v = sqrt(lhs.v.w);
return Value(vec4f(lhs.v.xyz / (2.0 * v), v));
}
fn op_floor(lhs: Value) -> Value {
return Value(vec4f(0.0, 0.0, 0.0, floor(lhs.v.w)));
}
fn op_ceil(lhs: Value) -> Value {
return Value(vec4f(0.0, 0.0, 0.0, ceil(lhs.v.w)));
}
fn op_round(lhs: Value) -> Value {
return Value(vec4f(0.0, 0.0, 0.0, round(lhs.v.w)));
}
fn op_square(lhs: Value) -> Value {
return op_mul(lhs, lhs);
}
fn op_sin(lhs: Value) -> Value {
let c = cos(lhs.v.w);
return Value(vec4f(lhs.v.xyz * c, sin(lhs.v.w)));
}
fn op_cos(lhs: Value) -> Value {
let s = -sin(lhs.v.w);
return Value(vec4f(lhs.v.xyz * s, cos(lhs.v.w)));
}
fn op_tan(lhs: Value) -> Value {
let c = cos(lhs.v.w);
let c2 = c * c;
return Value(vec4f(lhs.v.xyz / c2, tan(lhs.v.w)));
}
fn op_asin(lhs: Value) -> Value {
let r = sqrt(1.0 - lhs.v.w * lhs.v.w);
return Value(vec4f(lhs.v.xyz / r, asin(lhs.v.w)));
}
fn op_acos(lhs: Value) -> Value {
let r = sqrt(1.0 - lhs.v.w * lhs.v.w);
return Value(vec4f(-lhs.v.xyz / r, acos(lhs.v.w)));
}
fn op_atan(lhs: Value) -> Value {
let r = lhs.v.w * lhs.v.w + 1.0;
return Value(vec4f(lhs.v.xyz / r, atan(lhs.v.w)));
}
fn op_exp(lhs: Value) -> Value {
let v = exp(lhs.v.w);
return Value(vec4f(lhs.v.xyz * v, v));
}
fn op_log(lhs: Value) -> Value {
let v = log(lhs.v.w);
return Value(vec4f(lhs.v.xyz / lhs.v.w, v));
}
fn op_not(lhs: Value) -> Value {
return Value(vec4f(0.0, 0.0, 0.0, f32(lhs.v.w == 0.0)));
}
fn op_rand(lhs: Value) -> Value {
return Value(vec4f(0.0, 0.0, 0.0, rand(bitcast<u32>(lhs.v.w))));
}
fn op_compare(lhs: Value, rhs: Value) -> Value {
if lhs.v.w != lhs.v.w || rhs.v.w != rhs.v.w {
return Value(vec4f(0.0, 0.0, 0.0, nan_f32()));
} else if lhs.v.w < rhs.v.w {
return Value(vec4f(0.0, 0.0, 0.0, -1.0));
} else if lhs.v.w > rhs.v.w {
return Value(vec4f(0.0, 0.0, 0.0, 1.0));
} else {
return Value(vec4f(0.0, 0.0, 0.0, 0.0));
}
}
fn op_mix(lhs: Value, rhs: Value) -> Value {
let v = bitcast<f32>(mix(bitcast<u32>(lhs.v.w), bitcast<u32>(rhs.v.w)));
return Value(vec4f(0.0, 0.0, 0.0, v));
}
fn op_and(lhs: Value, rhs: Value, stack: ptr<function, Stack>) -> Value {
if lhs.v.w == 0.0 {
return lhs;
} else {
return rhs;
}
}
fn op_or(lhs: Value, rhs: Value, stack: ptr<function, Stack>) -> Value {
if lhs.v.w != 0.0 {
return lhs;
} else {
return rhs;
}
}
fn build_imm(v: f32) -> Value {
return Value(vec4f(0.0, 0.0, 0.0, v));
}
fn op_mod(lhs: Value, rhs: Value) -> Value {
let e = div_euclid(lhs.v.w, rhs.v.w);
return Value(vec4f(
lhs.v.xyz - rhs.v.xyz * e,
rem_euclid(lhs.v.w, rhs.v.w)
));
}
fn op_add(lhs: Value, rhs: Value) -> Value {
return Value(lhs.v + rhs.v);
}
fn op_sub(lhs: Value, rhs: Value) -> Value {
return Value(lhs.v - rhs.v);
}
fn op_min(lhs: Value, rhs: Value, stack: ptr<function, Stack>) -> Value {
if lhs.v.w < rhs.v.w {
return lhs;
} else {
return rhs;
}
}
fn op_max(lhs: Value, rhs: Value, stack: ptr<function, Stack>) -> Value {
if lhs.v.w > rhs.v.w {
return lhs;
} else {
return rhs;
}
}
fn op_mul(lhs: Value, rhs: Value) -> Value {
return Value(vec4f(
lhs.v.xyz * rhs.v.w + rhs.v.xyz * lhs.v.w,
lhs.v.w * rhs.v.w
));
}
fn op_div(lhs: Value, rhs: Value) -> Value {
let d = rhs.v.w * rhs.v.w;
return Value(vec4f(
(rhs.v.w * lhs.v.xyz - lhs.v.w * rhs.v.xyz) / d,
lhs.v.w / rhs.v.w
));
}
fn op_atan2(lhs: Value, rhs: Value) -> Value {
let d = rhs.v.w * rhs.v.w + lhs.v.w * lhs.v.w;
return Value(vec4f(
(rhs.v.w * lhs.v.xyz - lhs.v.w * rhs.v.xyz) / d,
atan2(lhs.v.w, rhs.v.w)
));
}