Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
lever/runtime/vectormath.py
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
678 lines (597 sloc)
20 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from math import sqrt, sin, cos, tan, pi, acos, asin, atan, atan2, pow as powf, exp, log, e, frexp, ldexp | |
from rpython.rlib.rfloat import INFINITY, NAN, DBL_MIN, DBL_MAX, DBL_EPSILON | |
from rpython.rtyper.lltypesystem import rffi | |
from rpython.rlib.rrandom import Random | |
from rpython.rlib.rarithmetic import r_uint, r_ulonglong | |
from space import * | |
import time | |
abs_ = Multimethod(1) | |
length = Multimethod(1) | |
#distance = Multimethod(2) | |
dot = Multimethod(2) | |
cross = Multimethod(2) | |
normalize = Multimethod(1) | |
#reflect = Multimethod(2) | |
#refract = Multimethod(3) | |
pow_ = Multimethod(2) | |
operators.coerce_by_default(pow_) | |
class Vec3(Object): | |
__slots__ = ['x', 'y', 'z'] | |
_immutable_fields_ = ['x', 'y', 'z'] | |
def __init__(self, x, y, z): | |
self.x = x | |
self.y = y | |
self.z = z | |
def getattr(self, name): | |
if name == u"x": | |
return Float(self.x) | |
if name == u"y": | |
return Float(self.y) | |
if name == u"z": | |
return Float(self.z) | |
if name == u"length": | |
return Integer(3) | |
return Object.getattr(self, name) | |
def iter(self): | |
return List([Float(self.x), Float(self.y), Float(self.z)]).iter() | |
def repr(self): | |
return u"vec3(%f, %f, %f)" % (self.x, self.y, self.z) | |
@Vec3.instantiator | |
def _(argv): | |
if len(argv) > 3: | |
raise OldError(u"Too many arguments to vec3") | |
xyz = [0.0, 0.0, 0.0] | |
for i, arg in enumerate(argv): | |
xyz[i] = to_float(arg) | |
return Vec3(xyz[0], xyz[1], xyz[2]) | |
@operators.add.multimethod_s(Vec3, Vec3) | |
def _(self, other): | |
return Vec3(self.x + other.x, self.y + other.y, self.z + other.z) | |
@operators.sub.multimethod_s(Vec3, Vec3) | |
def _(self, other): | |
return Vec3(self.x - other.x, self.y - other.y, self.z - other.z) | |
@operators.mul.multimethod_s(Vec3, Float) | |
def _(self, s): | |
return Vec3(self.x * s.number, self.y * s.number, self.z * s.number) | |
@operators.mul.multimethod_s(Float, Vec3) | |
def _(s, self): | |
return Vec3(s.number * self.x, s.number * self.y, s.number * self.z) | |
@operators.div.multimethod_s(Vec3, Float) | |
def _(self, s): | |
return Vec3(self.x / s.number, self.y / s.number, self.z / s.number) | |
@operators.div.multimethod_s(Float, Vec3) | |
def _(s, self): | |
return Vec3(s.number / self.x, s.number / self.y, s.number / self.z) | |
@length.multimethod_s(Vec3) | |
def _(v): | |
x, y, z = v.x, v.y, v.z | |
return Float(sqrt(x*x + y*y + z*z)) | |
#def distance(a, b): | |
# return length(a - b) | |
@dot.multimethod_s(Vec3, Vec3) | |
def _(a, b): | |
x0, y0, z0 = a.x, a.y, a.z | |
x1, y1, z1 = b.x, b.y, b.z | |
return Float(x0*x1 + y0*y1 + z0*z1) | |
@cross.multimethod_s(Vec3, Vec3) | |
def _(a, b): | |
x0, y0, z0 = a.x, a.y, a.z | |
x1, y1, z1 = b.x, b.y, b.z | |
return Vec3(y0*z1 - z0*y1, z0*x1 - x0*z1, x0*y1 - y0*x1) | |
@normalize.multimethod_s(Vec3) | |
def _(v): | |
x, y, z = v.x, v.y, v.z | |
d = sqrt(x*x + y*y + z*z) | |
if d > 0.0: | |
return Vec3(v.x / d, v.y / d, v.z / d) | |
return v | |
#def reflect(i, n): | |
# return i - 2.0 * dot(n, i) * n | |
# | |
#def refract(i, n, eta): | |
# ni = dot(n, i) | |
# k = 1.0 - eta * eta * (1.0 - ni*ni) | |
# return 0.0 if k < 0.0 else eta * i - (eta * ni + sqrt(k)) * n | |
class Quat(Object): | |
__slots__ = ['x', 'y', 'z', 'w'] | |
_immutable_fields_ = ['x', 'y', 'z', 'w'] | |
def __init__(self, x, y, z, w): | |
self.x = x | |
self.y = y | |
self.z = z | |
self.w = w | |
def getattr(self, name): | |
if name == u"x": | |
return Float(self.x) | |
if name == u"y": | |
return Float(self.y) | |
if name == u"z": | |
return Float(self.z) | |
if name == u"w": | |
return Float(self.w) | |
if name == u"length": | |
return Integer(4) | |
return Object.getattr(self, name) | |
def iter(self): | |
return List([Float(self.x), Float(self.y), Float(self.z), Float(self.w)]).iter() | |
@Quat.instantiator | |
def _(argv): | |
if len(argv) > 4: | |
raise OldError(u"Too many arguments to quat") | |
xyz = [0.0, 0.0, 0.0, 1.0] | |
for i, arg in enumerate(argv): | |
xyz[i] = to_float(arg) | |
return Quat(xyz[0], xyz[1], xyz[2], xyz[3]) | |
@Quat.builtin_method | |
def to_mat4(argv): | |
if len(argv) < 1: | |
raise OldError(u"Too few arguments") | |
q = argv[0] | |
if not isinstance(q, Quat): | |
raise OldError(u"Expected quaternion") | |
if len(argv) > 1: | |
p = argv[1] | |
if not isinstance(p, Vec3): | |
raise OldError(u"Expected vec3 as argument") | |
x, y, z = p.x, p.y, p.z | |
else: | |
x = y = z = 0.0 | |
sqx = q.x*q.x | |
sqy = q.y*q.y | |
sqz = q.z*q.z | |
sqw = q.w*q.w | |
# inverse only required if quaternion not normalized | |
invs = 1 / (sqx + sqy + sqz + sqw) | |
m00 = ( sqx - sqy - sqz + sqw)*invs | |
m11 = (-sqx + sqy - sqz + sqw)*invs | |
m22 = (-sqx - sqy + sqz + sqw)*invs | |
tmp1 = q.x*q.y | |
tmp2 = q.z*q.w | |
m10 = 2.0 * (tmp1 + tmp2)*invs | |
m01 = 2.0 * (tmp1 - tmp2)*invs | |
tmp1 = q.x*q.z | |
tmp2 = q.y*q.w | |
m20 = 2.0 * (tmp1 - tmp2)*invs | |
m02 = 2.0 * (tmp1 + tmp2)*invs | |
tmp1 = q.y*q.z | |
tmp2 = q.x*q.w | |
m21 = 2.0 * (tmp1 + tmp2)*invs | |
m12 = 2.0 * (tmp1 - tmp2)*invs | |
return Mat4([ | |
m00, m10, m20, 0.0, | |
m01, m11, m21, 0.0, | |
m02, m12, m22, 0.0, | |
x, y, z, 1.0]) | |
@Quat.builtin_method | |
@signature(Quat) | |
def invert(self): | |
dot = sqrt(self.x*self.x + self.y*self.y + self.z*self.z + self.w*self.w) | |
invDot = 1.0 / dot if dot > 0.0 else 0.0 | |
return Quat(-self.x*invDot, -self.y*invDot, -self.z*invDot, self.w*invDot) | |
@operators.neg.multimethod_s(Vec3) | |
def _(self): | |
return Vec3(-self.x, -self.y, -self.z) | |
@operators.neg.multimethod_s(Quat) | |
def _(self): | |
return Quat(-self.x, -self.y, -self.z, self.w) | |
@operators.pos.multimethod_s(Vec3) | |
def _(self): | |
return self | |
@operators.pos.multimethod_s(Quat) | |
def _(self): | |
return self | |
@operators.mul.multimethod_s(Quat, Quat) | |
def _(self, other): | |
ax, ay, az, aw = self.x, self.y, self.z, self.w | |
bx, by, bz, bw = other.x, other.y, other.z, other.w | |
return Quat( | |
ax * bw + aw * bx + ay * bz - az * by, | |
ay * bw + aw * by + az * bx - ax * bz, | |
az * bw + aw * bz + ax * by - ay * bx, | |
aw * bw - ax * bx - ay * by - az * bz) | |
# This is probably properly treated as a transform instead? | |
@operators.mul.multimethod_s(Quat, Vec3) | |
def _(self, other): | |
qx, qy, qz, qw = self.x, self.y, self.z, self.w | |
x, y, z = other.x, other.y, other.z | |
ix = qw * x + qy * z - qz * y | |
iy = qw * y + qz * x - qx * z | |
iz = qw * z + qx * y - qy * x | |
iw = -qx * x - qy * y - qz * z | |
return Vec3( | |
ix * qw + iw * -qx + iy * -qz - iz * -qy, | |
iy * qw + iw * -qy + iz * -qx - ix * -qz, | |
iz * qw + iw * -qz + ix * -qy - iy * -qx) | |
@Builtin | |
@signature(Vec3, Float) | |
def axisangle(v, angle): | |
angle = to_float(angle) | |
x, y, z = v.x, v.y, v.z | |
s = sin(angle * 0.5) | |
return Quat(s*x, s*y, s*z, cos(angle * 0.5)) | |
class Mat4(Object): | |
__slots__ = ['values'] | |
_immutable_fields_ = ['values[*]'] | |
def __init__(self, values): | |
self.values = list(values) | |
def getattr(self, name): | |
if name == u"length": | |
return Integer(16) | |
return Object.getattr(self, name) | |
def iter(self): | |
seq = [] | |
for x in self.values: | |
seq.append(Float(x)) | |
return List(seq).iter() | |
#def __repr__(self): | |
# return "mat4({})".format(self.values) | |
@Mat4.instantiator | |
def _(argv): | |
if len(argv) > 16: | |
raise OldError(u"Too many arguments to mat4") | |
mat = [1.0, 0.0, 0.0, 0.0, | |
0.0, 1.0, 0.0, 0.0, | |
0.0, 0.0, 1.0, 0.0, | |
0.0, 0.0, 0.0, 1.0] | |
for i, arg in enumerate(argv): | |
mat[i] = to_float(arg) | |
return Mat4(mat) | |
@Mat4.builtin_method | |
@signature(Mat4) | |
def transpose(self): | |
a = self.values | |
return Mat4([a[0], a[4], a[8], a[12], a[1], a[5], a[9], a[13], a[2], a[6], a[10], a[14], a[3], a[7], a[11], a[15]]) | |
@Mat4.builtin_method | |
@signature(Mat4) | |
def invert(self): | |
a = self.values | |
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; | |
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; | |
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; | |
a30 = a[12]; a31 = a[13]; a32 = a[14]; a33 = a[15]; | |
b00 = a00 * a11 - a01 * a10 | |
b01 = a00 * a12 - a02 * a10 | |
b02 = a00 * a13 - a03 * a10 | |
b03 = a01 * a12 - a02 * a11 | |
b04 = a01 * a13 - a03 * a11 | |
b05 = a02 * a13 - a03 * a12 | |
b06 = a20 * a31 - a21 * a30 | |
b07 = a20 * a32 - a22 * a30 | |
b08 = a20 * a33 - a23 * a30 | |
b09 = a21 * a32 - a22 * a31 | |
b10 = a21 * a33 - a23 * a31 | |
b11 = a22 * a33 - a23 * a32 | |
det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06 | |
if det == 0.0: | |
return None | |
det = 1.0 / det | |
return Mat4([ | |
(a11 * b11 - a12 * b10 + a13 * b09) * det, | |
(a02 * b10 - a01 * b11 - a03 * b09) * det, | |
(a31 * b05 - a32 * b04 + a33 * b03) * det, | |
(a22 * b04 - a21 * b05 - a23 * b03) * det, | |
(a12 * b08 - a10 * b11 - a13 * b07) * det, | |
(a00 * b11 - a02 * b08 + a03 * b07) * det, | |
(a32 * b02 - a30 * b05 - a33 * b01) * det, | |
(a20 * b05 - a22 * b02 + a23 * b01) * det, | |
(a10 * b10 - a11 * b08 + a13 * b06) * det, | |
(a01 * b08 - a00 * b10 - a03 * b06) * det, | |
(a30 * b04 - a31 * b02 + a33 * b00) * det, | |
(a21 * b02 - a20 * b04 - a23 * b00) * det, | |
(a11 * b07 - a10 * b09 - a12 * b06) * det, | |
(a00 * b09 - a01 * b07 + a02 * b06) * det, | |
(a31 * b01 - a30 * b03 - a32 * b00) * det, | |
(a20 * b03 - a21 * b01 + a22 * b00) * det]) | |
@Mat4.builtin_method | |
@signature(Mat4) | |
def adjoint(self): | |
a = self.values | |
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; | |
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; | |
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; | |
a30 = a[12]; a31 = a[13]; a32 = a[14]; a33 = a[15]; | |
return Mat4([ | |
(a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)), | |
-(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)), | |
(a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)), | |
-(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)), | |
-(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)), | |
(a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)), | |
-(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)), | |
(a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)), | |
(a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)), | |
-(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)), | |
(a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)), | |
-(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)), | |
-(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)), | |
(a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)), | |
-(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)), | |
(a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11))]) | |
@Mat4.builtin_method | |
@signature(Mat4) | |
def determinant(self): | |
a = self.values | |
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; | |
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; | |
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; | |
a30 = a[12]; a31 = a[13]; a32 = a[14]; a33 = a[15]; | |
b00 = a00 * a11 - a01 * a10 | |
b01 = a00 * a12 - a02 * a10 | |
b02 = a00 * a13 - a03 * a10 | |
b03 = a01 * a12 - a02 * a11 | |
b04 = a01 * a13 - a03 * a11 | |
b05 = a02 * a13 - a03 * a12 | |
b06 = a20 * a31 - a21 * a30 | |
b07 = a20 * a32 - a22 * a30 | |
b08 = a20 * a33 - a23 * a30 | |
b09 = a21 * a32 - a22 * a31 | |
b10 = a21 * a33 - a23 * a31 | |
b11 = a22 * a33 - a23 * a32 | |
return Float(b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06) | |
@Mat4.builtin_method | |
@signature(Mat4, Vec3) | |
def rotate_vec3(self, v): | |
a = self.values | |
x, y, z = v.x, v.y, v.z | |
return Vec3( | |
a[0]*x + a[4]*y + a[8]*z, | |
a[1]*x + a[5]*y + a[9]*z, | |
a[2]*x + a[6]*y + a[10]*z) | |
@operators.mul.multimethod_s(Mat4, Vec3) | |
def _(self, other): | |
a = self.values | |
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; | |
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; | |
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; | |
a30 = a[12]; a31 = a[13]; a32 = a[14]; a33 = a[15]; | |
x, y, z = other.x, other.y, other.z | |
return Vec3( | |
a00*x + a10*y + a20*z + a30, | |
a01*x + a11*y + a21*z + a31, | |
a02*x + a12*y + a22*z + a32) | |
@operators.mul.multimethod_s(Mat4, Mat4) | |
def _(self, other): | |
a = self.values | |
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; | |
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; | |
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; | |
a30 = a[12]; a31 = a[13]; a32 = a[14]; a33 = a[15]; | |
b = other.values | |
out = [0.0] * 16 | |
b0 = b[0]; b1 = b[1]; b2 = b[2]; b3 = b[3]; | |
out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30 | |
out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31 | |
out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32 | |
out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33 | |
b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; | |
out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30 | |
out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31 | |
out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32 | |
out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33 | |
b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; | |
out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30 | |
out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31 | |
out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32 | |
out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33 | |
b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; | |
out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30 | |
out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31 | |
out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32 | |
out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33 | |
return Mat4(out) | |
@Mat4.builtin_method | |
@signature(Mat4, Vec3) | |
def translate(self, v): | |
x, y, z = v.x, v.y, v.z | |
a = self.values | |
return Mat4(a[0:12] + [ | |
a[0] * x + a[4] * y + a[8] * z + a[12], | |
a[1] * x + a[5] * y + a[9] * z + a[13], | |
a[2] * x + a[6] * y + a[10] * z + a[14], | |
a[3] * x + a[7] * y + a[11] * z + a[15]]) | |
@Mat4.builtin_method | |
@signature(Mat4, Vec3) | |
def scale(self, v): | |
x, y, z = v.x, v.y, v.z | |
a = self.values | |
return Mat4([a[0]*x, a[1]*x, a[2]*x, a[3]*x, a[4]*y, a[5]*y, a[6]*y, a[7]*y, a[8]*z, a[9]*z, a[10]*z, a[11]*z, a[12], a[13], a[14], a[15]]) | |
@operators.clamp.multimethod_s(Float, Float, Float) | |
def clamp(x, low, high): | |
return Float(min(max(x.number, low.number), high.number)) | |
@operators.clamp.multimethod_s(Integer, Integer, Integer) | |
def clamp(x, low, high): | |
return Integer(min(max(x.value, low.value), high.value)) | |
# This may move into stdlib module eventually, possibly. | |
random = Random() | |
masklower = r_ulonglong(0xffffffff) | |
# This code might break again if r_ulonglong is treated as 32-bit int. | |
def init_random(): | |
n = r_ulonglong(time.time()) | |
key = [] | |
while n > 0: | |
key.append(r_uint(n & masklower)) | |
n >>= 32 | |
if len(key) == 0: | |
key.append(r_uint(0)) | |
random.init_by_array(key) | |
@abs_.multimethod_s(Float) | |
def abs_float(f): | |
return Float(-f.number) if f.number < 0.0 else f | |
@abs_.multimethod_s(Integer) | |
def abs_int(i): | |
return Integer(-i.value) if i.value < 0 else i | |
@Builtin | |
@signature() | |
def random_(): | |
return Float(random.random()) | |
@Builtin | |
@signature() | |
def random_circle(): | |
r = random.random() * 2.0 * pi | |
return Vec3(cos(r), sin(r), 0.0) | |
@Builtin | |
@signature() | |
def random_sphere(): | |
r = random.random() * 2.0 * pi | |
z = (random.random() * 2.0) - 1.0 | |
s = sqrt(1.0 - z*z) | |
return Vec3(cos(r) * s, sin(r) * s, z) | |
# These may also belong somewhere else, but they start here. | |
@Builtin | |
@signature(Float) | |
def sin_(f): | |
return Float(sin(f.number)) | |
@Builtin | |
@signature(Float) | |
def cos_(f): | |
return Float(cos(f.number)) | |
@Builtin | |
@signature(Float) | |
def tan_(f): | |
return Float(tan(f.number)) | |
@Builtin | |
@signature(Float) | |
def asin_(f): | |
return Float(asin(f.number)) | |
@Builtin | |
@signature(Float) | |
def acos_(f): | |
return Float(acos(f.number)) | |
@Builtin | |
@signature(Float) | |
def atan_(x): | |
return Float(atan(x.number)) | |
@Builtin | |
@signature(Float, Float) | |
def atan2_(y, x): | |
return Float(atan2(y.number, x.number)) | |
@Builtin | |
@signature(Float) | |
def sqrt_(f): | |
return Float(sqrt(f.number)) | |
@pow_.multimethod_s(Float, Float) | |
def pow_float(a, b): | |
try: | |
return Float(powf(a.number, b.number)) | |
except OverflowError as ovf: | |
raise unwind(LError(u"math range error")) | |
except ValueError as val: | |
raise unwind(LError(u"math domain error")) | |
@pow_.multimethod_s(Integer, Integer) | |
def pow_int(a, b): | |
try: | |
return Integer(powi(a.value, b.value)) | |
except OverflowError as ovf: | |
raise unwind(LError(u"math range error")) | |
except ValueError as val: | |
raise unwind(LError(u"math domain error")) | |
def powi(iv, iw): | |
temp = iv | |
ix = 1 | |
while iw > 0: | |
if iw & 1: | |
ix = ix * temp | |
iw >>= 1 # Shift exponent down by 1 bit | |
if iw == 0: | |
break | |
temp = temp * temp # Square the value of temp | |
return ix | |
@Builtin | |
@signature(Float) | |
def exp_(a): | |
return Float(exp(a.number)) | |
@Builtin | |
@signature(Float, Float) | |
def log_(a, b): | |
return Float(log(a.number) / log(b.number)) | |
@Builtin | |
@signature(Float) | |
def ln(a): | |
return Float(log(a.number)) | |
@Builtin | |
@signature(Float) | |
def sign(f): | |
if f.number < 0.0: | |
return Float(-1.0) | |
elif f.number > 0.0: | |
return Float(+1.0) | |
else: | |
return Float(0.0) | |
@Builtin | |
@signature(Object, Object, Object, Object) | |
def projection_matrix(fovy, aspect, znear, zfar): | |
fovy = to_float(fovy) | |
aspect = to_float(aspect) | |
znear = to_float(znear) | |
zfar = to_float(zfar) | |
f = 1/tan(fovy/2.0) | |
zd = znear-zfar | |
return Mat4([ | |
f/aspect, 0.0, 0.0, 0.0, | |
0.0, f, 0.0, 0.0, | |
0.0, 0.0, (zfar+znear) / zd, -1.0, | |
0.0, 0.0, (2*zfar*znear) / zd, 0.0 | |
]) | |
@Builtin | |
@signature(Float) | |
def frexp_(a): | |
mantissa, exponent = frexp(a.number) | |
return List([Float(mantissa), Integer(rffi.r_long(exponent))]) | |
@Builtin | |
@signature(Float, Integer) | |
def ldexp_(mantissa, exponent): | |
return Float(ldexp(mantissa.number, int(exponent.value))) | |
# This may not be a good approach to incrementing a float an epsilon ahead. | |
@Builtin | |
@signature(Float) | |
def next_increment(a): | |
mantissa, exponent = frexp(a.number) | |
if mantissa == 0.0: | |
return Float(DBL_MIN) | |
mantissa += DBL_EPSILON / 2.0 | |
return Float(ldexp(mantissa, exponent)) | |
by_symbol = { | |
u"vec3": Vec3.interface, | |
u"quat": Quat.interface, | |
u"mat4": Mat4.interface, | |
u"left": Vec3(-1.0, 0.0, 0.0), | |
u"right": Vec3(+1.0, 0.0, 0.0), | |
u"up": Vec3( 0.0,+1.0, 0.0), | |
u"down": Vec3( 0.0,-1.0, 0.0), | |
u"forward": Vec3( 0.0, 0.0,+1.0), | |
u"backward": Vec3( 0.0, 0.0,-1.0), | |
u"axisangle": axisangle, | |
u"random": random_, | |
u"random_circle": random_circle, | |
u"random_sphere": random_sphere, | |
u"length": length, | |
u"dot": dot, | |
u"cross": cross, | |
u"normalize": normalize, | |
u"sin": sin_, | |
u"cos": cos_, | |
u"tan": tan_, | |
u"sqrt": sqrt_, | |
u"pi": Float(pi), | |
u"tau": Float(pi*2), | |
u"projection_matrix": projection_matrix, | |
u"ldexp": ldexp_, | |
u"frexp": frexp_, | |
u"next_increment": next_increment, | |
u"abs": abs_, | |
u"sign": sign, | |
u"acos": acos_, | |
u"asin": asin_, | |
u"atan": atan_, | |
u"atan2": atan2_, | |
u"pow": pow_, | |
u"exp": exp_, | |
u"log": log_, | |
u"ln": ln, | |
u"e": Float(e), | |
u'inf': Float(INFINITY), | |
u'nan': Float(NAN), | |
u'dbl_min': Float(DBL_MIN), | |
u'dbl_max': Float(DBL_MAX), | |
u'dbl_epsilon': Float(DBL_EPSILON), | |
} |