- These objects are actually floating point numbers, but they are not accessible through TLISP in standard (IEEE 754) format.
- The format used is called "Metric" in the Euclid.h file found in the source code repository (Transcendence/Includes/Euclid.h), which is typedef double
- Microsoft's VC++ "double" is an 8 byte (64 bit) float, so therefore Vectors are a pair of 2 64-bit floating points
- The list format accessible through TLISP uses 4 pairs of 32 bit integers when accessed, which matches up exactly.
- A bit of experimentation shows, roughly:
- Transcendence defines LIGHT_SECOND = 299792.5, which is it's approximate value in kilometers.
- 1 light second = (sysVectorPolarOffset nil 0 1) -> (0 1091718210 0 0)
- X-coordinate of this is: (0 1091718210)
- 1 light second on the X component is = (0 1091718210)
- The hexadecimal notation for the second component = 0x41124C42
- Assuming this is an MSVC++ double type, this translates to 299792.5
- 2 light seconds / 2 light seconds = (sysVectorDivide (sysVectorPolarOffset nil 0 2) 599585) -> (0 1072693248 0 0)
- Again, assuming a standard IEEE 754 float form, this comes out to 1, as it should.
- Therefore, in to put all this in easy to understand terms:
- Vectors are MSVC++ double type numbers, stored broken bitwise into two 32 bit integers, stored little endian.
- List offset 0: Low bits of the mantissa.
- List offset 1: Sign bit in first binary position, following 8 digits are the exponent, remaining are the high bits of the mantissa.
Lisp-like languages typically have a "type" flag associated with their variables. TLISP is no exception, having types defined for int32, string, list, atom, etc. There need to be a few more "types" added to TLISP's repertoire to bring the scripting language "up to code", so to speak. Lisp-like languages also commonly split these groups into larger groupings, to facilitate translation between one type and another more transparently, should a function require or return a limited group of types:
- Vector: Currently just a list of size 4, with the above confusing double integer representation. This should be elevated to a first class type, distinguishable with (typeof x) as a "vector", which would aid greatly in keeping the source code sane and easier to implement further expansions and improvements to these elements.
- Float: Currently a list of size 2, only found paired up in Vectors. This could be changed to be a C++ double in memory, with the script parser being modified to understand 0.5, 1.5e10, and other common representations for floating points.
- Complex: With full support for Floating points, and the current support for vectors, Complex numbers could be implemented. Their form could either be represented in memory at Vectors currently are, as a list containing two Float types, or even as another bitwise breakdown of a native c++ type. The script parser would need to understand when these complex numbers are being given, either as a vector (x, i), something approaching Common LISP's format #C(x i), with a constructor (complex x i), or in algebraic form x + yi.
- Ratio: The type is already used when getting returns from the power function, when one gives fractional inputs as a list of size 2 with the following format: (list numeratorInteger denominatorInteger). The script parser would then need a change to understand fractional numbers given in the form 1/2 or 8%. However, with floating point support, the power function could be changed to only return floats or ints, depending on the type given, and the Ratio type could thusly be completely avoided.
Euclid.h also contains an array of utility functions which can be run on class CVector. Many of these would be extremely useful in TLISP, if they were to be exposed through the API:
- GetX and GetY: Does exactly what it says on the tin. Returns either component of the Vector as a floating point. Can be used in a geometric setting to help find the sine and cosine of a Vector, in a cheap way.
- SetX and SetY: Again, exactly what it says on the tin. Sets only the component specified.
- Norm: Normalizes a vector (set to be length 1, at the same angle as the original Vector).
- Perpendicular: Gives a Vector perpendicular to the given vector. (X, Y) -> (-Y, X)
- Reflect: Gives a Vector exactly opposite of the given vector. (X, Y) -> (-X, -Y)
- Rotate: Rotates a Vector by a given number of degrees.
- Other: There are also utility functions in this header file that would be directly useful for translating, rotating, scaling, and other operations that we currently cannot do with vectors, and often have need for