Motor

You are encouraged to solve this task according to the task description, using any language you may know.
- Related tasks
#include < stdlib.h>
#include < stdint.h>
#include < stddef.h>
#include < stdbool.h>
#include <stdalign.h>
#include < math.h>
/* default floating point type */
typedef float flt;
typedef vec (flt,4) quat(flt);
typedef quat(flt ) rotor;
typedef quat(flt ) screw;
typedef vec (flt,8) motor;
#define motor_rotor(m) *(rotor*)&(m)[0]
#define motor_screw(m) *(screw*)&(m)[4]
#include <array>
#include "vec.hpp"
template<class S>
constexpr SM_INLINE std::pair<S,S> sincos(S arg) { return { std::sin(arg), std::cos(arg) }; }
template<typename T, size_t N = 3>
struct alignas(2*sizeof(vec<T,N>)) line : std::array<vec<T,N>,2>
{
constexpr INLINE vec<T,N>& dir() { return (*this)[0]; }
constexpr INLINE vec<T,N>& pos() { return (*this)[1]; }
};
template<typename T>
struct quat : vec<T,4>
{
constexpr INLINE vec<T,3>& vector() { return this->xyz(); }
constexpr INLINE T& scalar() { return this->w(); }
};
template<typename T>
struct alignas(2*sizeof(quat<T>)) motor : std::array<quat<T>,2>
{
/* accessors */
constexpr INLINE quat<T>& rotor() { return (*this)[0]; }
constexpr INLINE quat<T>& screw() { return (*this)[1]; }
constexpr INLINE quat<T>& weight() { return (*this)[0]; }
constexpr INLINE quat<T>& bulk() { return (*this)[1]; }
constexpr INLINE quat<T>& v() { return (*this)[0]; }
constexpr INLINE quat<T>& m() { return (*this)[1]; }
constexpr INLINE motor<T>& unitize() { ((*this) *= (*this)[0].inv_mag()); }
motor<T>(const vec<T,3>& p, const vec<T,3>& q)
{
(*this)[0] = { 0.0F, 0.0F, 0.0F, -1.0F };
(*this)[1] = (p - q).dir();
}
motor<T>(const line<T,3>& k, const line<T,3>& l)
{
(*this)[0] = quat<T>(k.v() ^ l.m(), -dot(k.v(), l.v()));
(*this)[1] = quat<T>((l.v() ^ !k.m()) - (k.v() ^ !l.m()), -(l.v() ^ k.m()) - (k.v() ^ l.m()));
}
motor<T>(const plane<T,3>& g, const plane<T,3>& h)
{
v() = quat<T>(cross3(g,h),dot3(g,h));
m() = quat<T>(g.w * h.dir() - h.w * g.dir(), static_cast<T>(0));
}
};
template<typename T>
constexpr INLINE vec<T,3> cross3(motor<T> a, motor<T> b)
{
return a.rotor().yzx() * b.rotor().zxy()
- a.rotor().zxy() * b.rotor().yzx();
}
template<typename T>
constexpr INLINE motor<T> make_screw(T const angle, const line<T>& axis, T const disp)
{
auto const[s c] = sincos(angle / static_cast<T>(2));
return motor<T>{ (quat<T>)(axis.dir().pos() * (vec<T,4>){ s, s, s, c }),
(quat<T>)(axis.dir().pos() * (vec<T,4>){ c, c, c, -1 } * disp / static_cast<T>(2) +
axis.pos().pos() * (vec<T,4>){ s, s, s, s })};
}
template<typename T>
constexpr INLINE motor<T> make_rotation(T const angle, const line<T>& axis)
{
auto const[s c] = sincos(angle / static_cast<T>(2));
return motor<T>{ (quat<T>)(axis.dir().pos() * (vec<T,4>){ s, s, s, c }),(quat<T>)0};
}
template<typename T>
constexpr INLINE motor<T> make_translation(const vec<T,3>& offset)
{
return motor<T>{ (quat<T>)((vec<T,3>)0).pos(), (quat<T>)(offset / static_cast<T>(2)).dir() };
}
Type Vec4Flt
x As Single
y As Single
z As Single
w As Single
End Type
Type Vec8Flt
As Single dato(0 To 7)
End Type
Type quat_flt As Vec4Flt
Type rotor As quat_flt
Type screw As quat_flt
Type motor As Vec8Flt
#macro motor_rotor(motor_)
Cptr(rotor Ptr, @motor_)
#endmacro
#macro motor_screw(motor_)
Cptr(screw Ptr, Cptr(Any Ptr, @motor_) + 16) ' 4*Single = 16 bytes
#endmacro
' Example
Dim m As motor => { _
( 1.0, 0.0, 0.0, 0.0 ), _ ' rotor
( 0.0, 1.0, 0.0, 0.0 ) } ' screw
Print (*r).x ' 1.0
Print (*s).x ' 0.0 (screw x)
(*r).x = 2.0
Print m.dato(0) ' now 2.0
Sleep
Julia has the Quaternions package which defines a Quaternion -- for example, `Quaternion q(1, 2, 3, 4)` -- as a struct with members `q.s` as the real or scalar portion and `q.v1`, `q.v2`, and `q.v3` as the i, j, and k portions. A Quaternion can be used as a Motor type as in the C++ example. The Makie.jl plotting package uses Quaternions to define 3D plot rotations, though translations in the Makie package are usually defined with a different, 3D real number vector. A Quaternion may be defined for any Number derived type, including integer, floating point, rational, and complex numeric types.
Disclaimer: I dunno wat n.e. uv dis meanz.
with javascript_semantics
enum VECTOR, SCALAR
type quat(sequence q)
return sequence(q[VECTOR]) and atom(q[SCALAR])
end type
enum ROTOR, SCREW
type motor(sequence m)
return quat(m[ROTOR]) and quat(m[SCREW])
end type
function cross(motor a, b)
atom {aX,aY,aZ} = a[ROTOR][VECTOR],
{bX,bY,bZ} = b[ROTOR][VECTOR]
sequence a1 = {aY,aZ,aX},
a2 = {aZ,aX,aY},
b1 = {bZ,bX,bY},
b2 = {bY,bZ,bX}
quat res = {sq_sub(sq_mul(a1,b1),sq_mul(a2,b2)),0}
return res
end function
quat q1 = {{1,2,3},4},
q2 = {{5,6,7},8},
q3 = {{0,0,0},0}
motor m1 = {q1,q3},
m2 = {q2,q3}
printf(1,"m1: %v\n",{m1})
printf(1,"m2: %v\n",{m2})
printf(1,"m1 x m2: %v\n",{cross(m1,m2)})
- Output:
m1: {{{1,2,3},4},{{0,0,0},0}}
m2: {{{5,6,7},8},{{0,0,0},0}}
m1 x m2: {{-4,8,-4},0}
As there's no task description as such, I assume that the task is to create a representation of a Motor variable in one's language though as the C/C++ examples don't make any attempt to define split-complex numbers, I've stuck with real numbers for now.
As far as the 'cross3' function is concerned, I'm not sure whether vector3 or quaternion multiplication is required - I've assumed the former for now as there's no scalar (or 'screw') term involved and nothing in the C++ code to indicate that 'quat' is a true quaternion.
Pluto has a built in vector3 class so I've used that.
local vector3 = require "pluto:vector3"
class quat
public x, y, z, w
function __construct(v3, w)
assert(v3 instanceof vector3, "argument #1 must be a vector3")
assert(type(w) == "number", "argument #2 must be a number")
self.x = v3.x
self.y = v3.y
self.z = v3.z
self.w = w
end
function __tostring() return $"({self.x}, {self.y}, {self.z}, {self.w})" end
end
class motor
static function cross3(a, b)
assert(a instanceof motor, "argument #1 must be a motor")
assert(a instanceof motor, "argument #2 must be a motor")
local a1 = vector3(a.rotor.y, a.rotor.z, a.rotor.x)
local a2 = vector3(a.rotor.z, a.rotor.x, a.rotor.y)
local b1 = vector3(b.rotor.y, b.rotor.z, b.rotor.x)
local b2 = vector3(b.rotor.z, b.rotor.x, b.rotor.y)
return new quat(a1 * b2 - a2 * b1, 0)
end
function __construct(public rotor, public screw)
assert(rotor instanceof quat, "argument #1 must be a quat")
assert(screw instanceof quat, "argument #2 must be a quat")
end
function __tostring() return $"({self.rotor}, {self.screw})" end
end
local vec1 = vector3(1, 2, 3)
local w1 = 4
local q1 = new quat(vec1, w1)
local vec2 = vector3(5, 6, 7)
local w2 = 8
local q2 = new quat(vec2, w2)
local vec3 = vector3(0, 0, 0)
local w3 = 0
local q3 = new quat(vec3, w3)
local m1 = new motor(q1, q3)
local m2 = new motor(q2, q3)
print($"m1: {m1}")
print($"m2: {m2}")
print($"m1 x m2 = {motor.cross3(m1, m2)}")
- Output:
m1: ((1, 2, 3, 4), (0, 0, 0, 0)) m2: ((5, 6, 7, 8), (0, 0, 0, 0)) m1 x m2 = (-4, 8, -4, 0)
import "./vector" for Vector3
// Vector3 class only defines multiplication by a scalar.
var Vmul = Fn.new { |v1, v2|
return Vector3.new(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z)
}
class Quat {
construct new(v3, w) {
if (!(v3 is Vector3)) Fiber.abort("Argument #1 must be a Vector3.")
if (!(w is Num)) Fiber.abort("Argument #2 must be a Num.")
_x = v3.x
_y = v3.y
_z = v3.z
_w = w
}
x { _x }
y { _y }
z { _z }
w { _w }
toString { "(%(_x), %(_y), %(_z), %(_w))" }
}
class Motor {
static cross3(a, b) {
if (!(a is Motor)) Fiber.abort("Argument #1 must be a Motor.")
if (!(b is Motor)) Fiber.abort("Argument #2 must be a Motor.")
var a1 = Vector3.new(a.rotor.y, a.rotor.z, a.rotor.x)
var a2 = Vector3.new(a.rotor.z, a.rotor.x, a.rotor.y)
var b1 = Vector3.new(b.rotor.y, b.rotor.z, b.rotor.x)
var b2 = Vector3.new(b.rotor.z, b.rotor.x, b.rotor.y)
return Quat.new(Vmul.call(a1, b2) - Vmul.call(a2, b1), 0)
}
construct new(rotor, screw) {
if (!(rotor is Quat)) Fiber.abort("Argument #1 must be a Quat.")
if (!(screw is Quat)) Fiber.abort("Argument #2 must be a Quat.")
_r = rotor
_s = screw
}
rotor { _r }
screw { _s }
toString { "(%(_r), %(_s))" }
}
var vec1 = Vector3.new(1, 2, 3)
var w1 = 4
var q1 = Quat.new(vec1, w1)
var vec2 = Vector3.new(5, 6, 7)
var w2 = 8
var q2 = Quat.new(vec2, w2)
var vec3 = Vector3.new(0, 0, 0)
var w3 = 0
var q3 = Quat.new(vec3, w3)
var m1 = Motor.new(q1, q3)
var m2 = Motor.new(q2, q3)
System.print("m1: %(m1)")
System.print("m2: %(m2)")
System.print("m1 x m2 = %(Motor.cross3(m1, m2))")
- Output:
m1: ((1, 2, 3, 4), (0, 0, 0, 0)) m2: ((5, 6, 7, 8), (0, 0, 0, 0)) m1 x m2 = (-4, 8, -4, 0)