Files
solvecraft/harness/cpp/shim/geom_vector3d.cpp
T
bherbruck 367927455d geom.vector3d: port SmVector3d and SmMath sqrt/cbrt/acos/asin
Vec3 moves from math.rs into geom::vector3d (re-exported from math).
Wires UNPORTED(geom.vector3d) in geom::tol (AreParallel/ArePerpendicular)
and replaces the CO-PORT copies in tol, vector2d and extent3d.
difftest: 6114 cases, all bit-identical; geom.tol now 3430/3430, 0 deferred.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 15:58:55 -04:00

270 lines
10 KiB
C++

// SPDX-License-Identifier: Apache-2.0
// difftest shim for unit `geom.vector3d`.
// Wraps upstream SmVector3d (source/SMLib/inc/SmVector3d.h, source/SMLib/src/SmVector3d.cpp)
// and sm_sqrt / sm_cbrt / sm_acos / sm_asin (source/SMLib/src/SmMath.cpp).
#include "sc_shim.h"
#include <SmMath.h>
#include <SmVector2d.h>
#include <SmVector3d.h>
// Operation codes (keep in sync with crates/solidcore-ffi/src/units/geom_vector3d.rs).
enum ScVec3Op : int32_t
{
OP_LENGTH_SQUARED = 0, // a.LengthSquared()
OP_LENGTH = 1, // a.Length()
OP_DOT = 2, // a.Dot(b)
OP_CROSS = 3, // a * b
OP_NEG = 4, // -a
OP_ADD = 5, // a + b
OP_SUB = 6, // a - b
OP_MUL = 7, // a * s
OP_LMUL = 8, // s * a
OP_DIV = 9, // a / s
OP_UNITIZE = 10, // a.Unitize() (status or vector)
OP_UNITIZE_OR_Z = 11, // a.Unitize(FALSE), status ignored
OP_TRIPLE = 12, // a.TripleProduct(b, c)
OP_NORMAL_IN_PLANE = 13, // a.NormalInPlane(b)
OP_MAX_DIM = 14, // a.GetMaxDimension()
OP_MIN_DIM = 15, // a.GetMinDimension()
OP_PARALLEL = 16, // a.IsParallelTo(b, s, &anti) -> [ret, anti or -1]
OP_PERPENDICULAR = 17, // a.IsPerpendicularTo(b, s)
OP_PROJ = 18, // a.ProjectToPlane(b)
OP_PROJ_PT = 19, // a.ProjectPointToPlane(b, c)
OP_ROT_PROJ = 20, // a.RotateProjectToPlane(b, c)
OP_ROT_PROJ_PT = 21, // a.RotateProjectPointToPlane(b, c, d)
OP_PERSP_PROJ = 22, // a.PerspectiveProjectToPlane(b, c, d, e)
OP_PERSP_PROJ_PT = 23, // a.PerspectiveProjectPointToPlane(b, c, d)
OP_DISTANCE = 24, // a.DistanceBetween(b)
OP_DISTANCE_SQ = 25, // a.DistanceBetweenSquared(b)
OP_CLOSER_THAN = 26, // a.CloserThan(s, b)
OP_MULTIPLY = 27, // a.Multiply(b)
OP_DERIV_CROSS = 28, // a.DerivativeOfCrossProduct(b, c, d)
OP_SOLVE2 = 29, // a.SolveTwoLinearEquations(b, out) (status or [x, y])
OP_INDEX = 30, // a[idx] (const)
OP_INDEX_SET = 31, // a[idx] = s (non-const)
OP_EQ = 32, // a == b
OP_ADD_ASSIGN = 33, // a += b
OP_SUB_ASSIGN = 34, // a -= b
OP_MUL_ASSIGN = 35, // a *= s
OP_DIV_ASSIGN = 36, // a /= s
OP_INSIDE_SECTOR = 37, // a.IsInsideSector(b, c, d)
OP_ORTHO = 38, // a.MakeUnitOrthoVectors(flag ? &b : NULL, x, y, z)
OP_ROTATE_AXIS = 39, // a.RotateVecAboutAxis(b, s)
OP_UNIT_DERIV = 40, // a.UnitizedDerivative(b)
OP_UNIT_DERIV2 = 41, // a.UnitizedDerivative2(b, c, o1, o2) -> [failed, o1, o2]
OP_UNIT_DERIV3 = 42, // a.UnitizedDerivative3(b, c, d, o1, o2, o3) -> [failed, o1, o2, o3]
OP_ANGLE = 43, // a.AngleBetween(b, ang)
OP_CCW_ANGLE = 44, // a.CCWAngleBetween(b, c, ang)
OP_COLINEAR = 45, // a.IsColinearWith(b, c, d)
OP_IS_INITIALIZED = 46, // a.IsInitialized()
OP_IS_UNDEF = 47, // a.IsUndef()
OP_IS_ZERO = 48, // a.IsZero(s)
OP_IS_2D = 49, // a.Is2d()
OP_FROM_NL = 50, // SmVector3d({a.x, a.y, a.z, s}, true)
OP_BETWEEN = 51, // SmVector3d(a, b)
OP_FROM_VEC2 = 52, // SmVector3d(SmVector2d(a.x, a.y))
OP_COPY = 53, // SmVector3d(double*), copy ctor, operator=, Copy, Set, Swap
OP_UNINITIALIZED = 54, // a.SetUninitialized()
OP_SQRT = 55, // sm_sqrt(s)
OP_CBRT = 56, // sm_cbrt(s)
OP_ACOS = 57, // sm_acos(s)
OP_ASIN = 58, // sm_asin(s)
};
#define SC_V3_MAX_OUT 10
// Runs one SmVector3d operation.
// v[15] : five vector operands a, b, c, d, e (x, y, z each)
// s : scalar operand
// idx : index operand (OP_INDEX: 0..5, OP_INDEX_SET: 0..2; checked by the caller)
// flag : OP_ORTHO: nonzero passes &b as the Y reference, else NULL
// out[10] : result values; *out_n receives how many were written
// Returns 0, the upstream SmStatus of a failed call, or SC_ERR_ARG.
SC_EXPORT int32_t sc_geom_vector3d_op(int32_t op, const double* v, double s, int32_t idx,
int32_t flag, double* out, int32_t* out_n)
{
SC_TRY
SmVector3d a(v[0], v[1], v[2]);
SmVector3d b(v[3], v[4], v[5]);
SmVector3d c(v[6], v[7], v[8]);
SmVector3d d(v[9], v[10], v[11]);
SmVector3d e(v[12], v[13], v[14]);
*out_n = 0;
auto put = [&](double x) { out[(*out_n)++] = x; };
auto put1 = [&](double x) {
put(x);
return (int32_t)SC_OK;
};
auto putv = [&](const SmVector3d& r) {
put(r.x);
put(r.y);
put(r.z);
};
auto put3 = [&](const SmVector3d& r) {
putv(r);
return (int32_t)SC_OK;
};
auto flg = [](SmBoolean x) { return x ? 1.0 : 0.0; };
switch (op)
{
case OP_LENGTH_SQUARED: return put1(a.LengthSquared());
case OP_LENGTH: return put1(a.Length());
case OP_DOT: return put1(a.Dot(b));
case OP_CROSS: return put3(a * b);
case OP_NEG: return put3(-a);
case OP_ADD: return put3(a + b);
case OP_SUB: return put3(a - b);
case OP_MUL: return put3(a * s);
case OP_LMUL: return put3(s * a);
case OP_DIV: return put3(a / s);
case OP_UNITIZE:
{
SmStatus st = a.Unitize();
if (st != SM_SUCCESS)
return (int32_t)st;
return put3(a);
}
case OP_UNITIZE_OR_Z: a.Unitize(FALSE); return put3(a);
case OP_TRIPLE: return put1(a.TripleProduct(b, c));
case OP_NORMAL_IN_PLANE: return put3(a.NormalInPlane(b));
case OP_MAX_DIM: return put1(a.GetMaxDimension());
case OP_MIN_DIM: return put1(a.GetMinDimension());
case OP_PARALLEL:
{
SmBoolean anti = 7;
SmBoolean r = a.IsParallelTo(b, s, &anti);
put(flg(r));
return put1(anti == 7 ? -1.0 : flg(anti));
}
case OP_PERPENDICULAR: return put1(flg(a.IsPerpendicularTo(b, s)));
case OP_PROJ: return put3(a.ProjectToPlane(b));
case OP_PROJ_PT: return put3(a.ProjectPointToPlane(b, c));
case OP_ROT_PROJ: return put3(a.RotateProjectToPlane(b, c));
case OP_ROT_PROJ_PT: return put3(a.RotateProjectPointToPlane(b, c, d));
case OP_PERSP_PROJ: return put3(a.PerspectiveProjectToPlane(b, c, d, e));
case OP_PERSP_PROJ_PT: return put3(a.PerspectiveProjectPointToPlane(b, c, d));
case OP_DISTANCE: return put1(a.DistanceBetween(b));
case OP_DISTANCE_SQ: return put1(a.DistanceBetweenSquared(b));
case OP_CLOSER_THAN: return put1(flg(a.CloserThan(s, b)));
case OP_MULTIPLY: return put3(a.Multiply(b));
case OP_DERIV_CROSS: return put3(a.DerivativeOfCrossProduct(b, c, d));
case OP_SOLVE2:
{
SmPoint2d sol(0.0, 0.0);
SmStatus st = a.SolveTwoLinearEquations(b, sol);
if (st != SM_SUCCESS)
return (int32_t)st;
put(sol.x);
return put1(sol.y);
}
case OP_INDEX:
{
if (idx < 0 || idx > 5)
return SC_ERR_ARG;
const SmVector3d& ca = a;
return put1(ca[(ULONG)idx]);
}
case OP_INDEX_SET:
if (idx < 0 || idx > 2)
return SC_ERR_ARG;
a[(ULONG)idx] = s;
return put3(a);
case OP_EQ: return put1((a == b) ? 1.0 : 0.0);
case OP_ADD_ASSIGN: a += b; return put3(a);
case OP_SUB_ASSIGN: a -= b; return put3(a);
case OP_MUL_ASSIGN: a *= s; return put3(a);
case OP_DIV_ASSIGN: a /= s; return put3(a);
case OP_INSIDE_SECTOR: return put1(flg(a.IsInsideSector(b, c, d)));
case OP_ORTHO:
{
SmVector3d x, y, z;
SmStatus st = a.MakeUnitOrthoVectors(flag ? &b : NULL, x, y, z);
if (st != SM_SUCCESS)
return (int32_t)st;
putv(x);
putv(y);
return put3(z);
}
case OP_ROTATE_AXIS: return put3(a.RotateVecAboutAxis(b, s));
case OP_UNIT_DERIV: return put3(a.UnitizedDerivative(b));
case OP_UNIT_DERIV2:
{
SmVector3d o1(0, 0, 0), o2(0, 0, 0);
SmStatus st = a.UnitizedDerivative2(b, c, o1, o2);
put(st == SM_SUCCESS ? 0.0 : (double)st);
putv(o1);
return put3(o2);
}
case OP_UNIT_DERIV3:
{
SmVector3d o1(0, 0, 0), o2(0, 0, 0), o3(0, 0, 0);
SmStatus st = a.UnitizedDerivative3(b, c, d, o1, o2, o3);
put(st == SM_SUCCESS ? 0.0 : (double)st);
putv(o1);
putv(o2);
return put3(o3);
}
case OP_ANGLE:
{
double ang = -1.0;
SmStatus st = a.AngleBetween(b, ang);
if (st != SM_SUCCESS)
return (int32_t)st;
return put1(ang);
}
case OP_CCW_ANGLE:
{
double ang = -1.0;
SmStatus st = a.CCWAngleBetween(b, c, ang);
if (st != SM_SUCCESS)
return (int32_t)st;
return put1(ang);
}
case OP_COLINEAR: return put1(flg(a.IsColinearWith(b, c, d)));
case OP_IS_INITIALIZED: return put1(flg(a.IsInitialized()));
case OP_IS_UNDEF: return put1(flg(a.IsUndef()));
case OP_IS_ZERO: return put1(flg(a.IsZero(s)));
case OP_IS_2D: return put1(flg(a.Is2d()));
case OP_FROM_NL:
{
double p[4] = {v[0], v[1], v[2], s};
SmVector3d r(p, true);
return put3(r);
}
case OP_BETWEEN:
{
SmVector3d r(a, b);
return put3(r);
}
case OP_FROM_VEC2:
{
SmVector2d v2(v[0], v[1]);
SmVector3d r(v2);
return put3(r);
}
case OP_COPY:
{
double arr[3] = {v[0], v[1], v[2]};
SmVector3d c1(arr);
SmVector3d c2(c1);
SmVector3d c3;
c3 = c2;
SmVector3d c4;
c4.Copy(c3);
SmVector3d c5(0, 0, 0);
c5.Set(c4.x, c4.y, c4.z);
SmVector3d c6(1, 2, 3);
c6.Swap(c5);
return put3(c6);
}
case OP_UNINITIALIZED: a.SetUninitialized(); return put3(a);
case OP_SQRT: return put1(sm_sqrt(s));
case OP_CBRT: return put1(sm_cbrt(s));
case OP_ACOS: return put1(sm_acos(s));
case OP_ASIN: return put1(sm_asin(s));
default: return SC_ERR_ARG;
}
SC_CATCH
}