Files
solvecraft/harness/cpp/shim/geom_vector2d.cpp
T
bherbruck 34de6d49f1 geom.vector2d: port SmVector2d (Vec2) with difftest runner
Vec2 moves from math to geom::vector2d (re-exported from math). Back-edges
sm_sqrt/sm_acos/sm_asin and SM_IS_ZERO_SQUARED are co-ported as private
helpers. difftest: 4060 cases bit-identical.

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

144 lines
4.9 KiB
C++

// SPDX-License-Identifier: Apache-2.0
// difftest shim for unit `geom.vector2d`.
// Wraps upstream SmVector2d (source/SMLib/inc/SmVector2d.h, source/SMLib/src/SmVector2d.cpp).
#include "sc_shim.h"
#include <SmVector2d.h>
#include <SmVector3d.h>
// Operation codes (keep in sync with crates/solidcore-ffi/src/units/geom_vector2d.rs).
enum ScVec2Op : int32_t
{
OP_LENGTH_SQUARED = 0, // a.LengthSquared()
OP_LENGTH = 1, // a.Length()
OP_DOT = 2, // a.Dot(b)
OP_NEG = 3, // -a
OP_ADD = 4, // a + b
OP_SUB = 5, // a - b
OP_MUL = 6, // a * s
OP_LMUL = 7, // s * a
OP_DIV = 8, // a / s
OP_UNITIZE = 9, // a.Unitize()
OP_DISTANCE = 10, // a.DistanceBetween(b)
OP_DISTANCE_SQ = 11, // a.DistanceBetweenSquared(b)
OP_CLOSER_THAN = 12, // a.CloserThan(s, b)
OP_MAX_DIMENSION = 13, // a.GetMaxDimension()
OP_SWAP_XY = 14, // a.SwapXY()
OP_ROTATE = 15, // a.Rotate(s)
OP_EQ = 16, // a == b
OP_NE = 17, // a != b
OP_INDEX = 18, // a[idx] (const)
OP_INDEX_SET = 19, // a[idx] = s (non-const)
OP_ADD_ASSIGN = 20, // a += b
OP_SUB_ASSIGN = 21, // a -= b
OP_MUL_ASSIGN = 22, // a *= s
OP_ANGLE = 23, // a.AngleBetween(b, ang)
OP_CCW_ANGLE = 24, // a.CCWAngleBetween(b, ang)
OP_IS_ZERO = 25, // a.IsZero(s)
OP_IS_INITIALIZED = 26, // a.IsInitialized()
OP_FROM_VEC3 = 27, // v2 = SmVector3d(a.x, a.y, s)
OP_UNINITIALIZED = 28, // a.SetUninitialized()
OP_COPY = 29, // SmVector2d(double*), copy ctor, operator=, Copy, Set
};
// Runs one SmVector2d operation.
// a[2], b[2] : vector operands (x, y)
// s : scalar operand
// idx : index operand (OP_INDEX / OP_INDEX_SET; caller guarantees 0 or 1)
// out[2] : result values; *out_n receives how many were written (1 or 2)
// Returns 0, the upstream SmStatus of a failed call, or SC_ERR_ARG.
SC_EXPORT int32_t sc_geom_vector2d_op(int32_t op, const double* a, const double* b, double s,
int32_t idx, double* out, int32_t* out_n)
{
SC_TRY
SmVector2d va(a[0], a[1]);
SmVector2d vb(b[0], b[1]);
SmVector2d r;
*out_n = 0;
auto put1 = [&](double v) {
out[0] = v;
*out_n = 1;
return (int32_t)SC_OK;
};
auto put2 = [&](const SmVector2d& v) {
out[0] = v.x;
out[1] = v.y;
*out_n = 2;
return (int32_t)SC_OK;
};
switch (op)
{
case OP_LENGTH_SQUARED: return put1(va.LengthSquared());
case OP_LENGTH: return put1(va.Length());
case OP_DOT: return put1(va.Dot(vb));
case OP_NEG: return put2(-va);
case OP_ADD: return put2(va + vb);
case OP_SUB: return put2(va - vb);
case OP_MUL: return put2(va * s);
case OP_LMUL: return put2(s * va);
case OP_DIV: return put2(va / s);
case OP_UNITIZE:
{
SmStatus st = va.Unitize();
if (st != SM_SUCCESS)
return (int32_t)st;
return put2(va);
}
case OP_DISTANCE: return put1(va.DistanceBetween(vb));
case OP_DISTANCE_SQ: return put1(va.DistanceBetweenSquared(vb));
case OP_CLOSER_THAN: return put1(va.CloserThan(s, vb) ? 1.0 : 0.0);
case OP_MAX_DIMENSION: return put1(va.GetMaxDimension());
case OP_SWAP_XY: va.SwapXY(); return put2(va);
case OP_ROTATE: return put2(va.Rotate(s));
case OP_EQ: return put1((va == vb) ? 1.0 : 0.0);
case OP_NE: return put1((va != vb) ? 1.0 : 0.0);
case OP_INDEX:
{
if (idx != 0 && idx != 1)
return SC_ERR_ARG;
const SmVector2d& cva = va;
return put1(cva[(ULONG)idx]);
}
case OP_INDEX_SET:
if (idx != 0 && idx != 1)
return SC_ERR_ARG;
va[(ULONG)idx] = s;
return put2(va);
case OP_ADD_ASSIGN: va += vb; return put2(va);
case OP_SUB_ASSIGN: va -= vb; return put2(va);
case OP_MUL_ASSIGN: va *= s; return put2(va);
case OP_ANGLE:
case OP_CCW_ANGLE:
{
double ang = -1.0;
SmStatus st = (op == OP_ANGLE) ? va.AngleBetween(vb, ang) : va.CCWAngleBetween(vb, ang);
if (st != SM_SUCCESS)
return (int32_t)st;
return put1(ang);
}
case OP_IS_ZERO: return put1(va.IsZero(s) ? 1.0 : 0.0);
case OP_IS_INITIALIZED: return put1(va.IsInitialized() ? 1.0 : 0.0);
case OP_FROM_VEC3:
{
SmVector3d v3(a[0], a[1], s);
r = v3;
return put2(r);
}
case OP_UNINITIALIZED: va.SetUninitialized(); return put2(va);
case OP_COPY:
{
double arr[2] = {a[0], a[1]};
SmVector2d c1(arr);
SmVector2d c2(c1);
SmVector2d c3;
c3 = c2;
SmVector2d c4;
c4.Copy(c3);
r.Set(c4.x, c4.y);
return put2(r);
}
default: return SC_ERR_ARG;
}
SC_CATCH
}