From b8fd0873191f5071ca2a8724ba92439edd0c0a37 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 18 Feb 2026 13:44:57 -0500 Subject: [PATCH 01/32] + xo-numeric/ [WIP] --- CMakeLists.txt | 42 ++++++++++ NumericDispatch.hpp | 44 +++++++++++ cmake/xo-bootstrap-macros.cmake | 41 ++++++++++ cmake/xo_numericConfig.cmake.in | 15 ++++ idl/Numeric.json5 | 75 ++++++++++++++++++ include/xo/numeric/Numeric.hpp | 22 ++++++ include/xo/numeric/NumericDispatch.hpp | 20 +++++ include/xo/numeric/NumericOps.hpp | 44 +++++++++++ include/xo/numeric/detail/ANumeric.hpp | 70 +++++++++++++++++ include/xo/numeric/detail/INumeric_Any.hpp | 87 +++++++++++++++++++++ include/xo/numeric/detail/INumeric_Xfer.hpp | 79 +++++++++++++++++++ include/xo/numeric/detail/RNumeric.hpp | 81 +++++++++++++++++++ src/numeric/INumeric_Any.cpp | 41 ++++++++++ 13 files changed, 661 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 NumericDispatch.hpp create mode 100644 cmake/xo-bootstrap-macros.cmake create mode 100644 cmake/xo_numericConfig.cmake.in create mode 100644 idl/Numeric.json5 create mode 100644 include/xo/numeric/Numeric.hpp create mode 100644 include/xo/numeric/NumericDispatch.hpp create mode 100644 include/xo/numeric/NumericOps.hpp create mode 100644 include/xo/numeric/detail/ANumeric.hpp create mode 100644 include/xo/numeric/detail/INumeric_Any.hpp create mode 100644 include/xo/numeric/detail/INumeric_Xfer.hpp create mode 100644 include/xo/numeric/detail/RNumeric.hpp create mode 100644 src/numeric/INumeric_Any.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..c762fbfa --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,42 @@ +# xo-numeric/CMakeLists.txt + +cmake_minimum_required(VERSION 3.10) + +project(xo_numeric VERSION 1.0) +enable_language(CXX) + +include(GNUInstallDirs) +include(cmake/xo-bootstrap-macros.cmake) + +xo_cxx_toplevel_options3() + +# ---------------------------------------------------------------- +# c++ settings + +# one-time project-specific c++ flags. usually empty +set(PROJECT_CXX_FLAGS "") +add_definitions(${PROJECT_CXX_FLAGS}) + +# ---------------------------------------------------------------- +# output targets + +# note: manual target; generated code committed to git +xo_add_genfacet( + TARGET xo-numeric-facet-numeric + FACET Numeric + INPUT idl/Numeric.json5 + ) + +# ---------------------------------------------------------------- + +xo_add_genfacet_all(xo-numeric-genfacet-all) + +# ---------------------------------------------------------------- + +#add_subdirectory(src/numeric) # NOTE: will need cmake export here +#add_subdirectory(utest) + +# ---------------------------------------------------------------- +# cmake export + + diff --git a/NumericDispatch.hpp b/NumericDispatch.hpp new file mode 100644 index 00000000..a312c1c1 --- /dev/null +++ b/NumericDispatch.hpp @@ -0,0 +1,44 @@ +/** @file NumericDispatch.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +//#include // probably will need this at some point? +#include +#include + +namespace xo { + namespace scm { + + /** type-erased arithmetic dispatch. + **/ + struct NumericOps { + obj + }; + + class NumericDispatch { + public: + using KeyType = std::pair; + using MapType = xo::map::DArenaHashMap + + /** combine two typeseq's to get hash value **/ + struct KeyHash { + std::size_t operator()(const key_type & k) const noexcept { + // combine the two seqno values + std::size_t h1 = std::hash{}(k.first.seqno()); + std::size_t h2 = std::hash{}(k.second.seqno()); + return h1 ^ (h2 << 1); + } + }; + + + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end NumericDispqatch.hpp */ + + diff --git a/cmake/xo-bootstrap-macros.cmake b/cmake/xo-bootstrap-macros.cmake new file mode 100644 index 00000000..592272c0 --- /dev/null +++ b/cmake/xo-bootstrap-macros.cmake @@ -0,0 +1,41 @@ +# ---------------------------------------------------------------- +# for example: +# $ PREFIX=/usr/local # for example +# $ cmake -DCMAKE_MODULE_PATH=prefix -DCMAKE_INSTALL_PREFIX=$PREFIX -B .build +# +# will get +# CMAKE_MODULE_PATH +# from xo-cmake-config --cmake-module-path +# +# and expect .cmake macros in +# CMAKE_MODULE_PATH/xo_macros/xo_cxx.cmake +# ---------------------------------------------------------------- + +find_program(XO_CMAKE_CONFIG_EXECUTABLE NAMES xo-cmake-config REQUIRED) + +if ("${XO_CMAKE_CONFIG_EXECUTABLE}" STREQUAL "XO_CMAKE_CONFIG_EXECUTABLE-NOT_FOUND") + message(FATAL "could not find xo-cmake-config executable") +endif() + +message(STATUS "XO_CMAKE_CONFIG_EXECUTABLE=${XO_CMAKE_CONFIG_EXECUTABLE}") + +if (XO_SUBMODULE_BUILD) + if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix)) + # local version of xo-cmake macros + set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/xo-cmake/cmake") + message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") + endif() +else() + if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix)) + # default to typical install location for xo-project-macros + execute_process(COMMAND ${XO_CMAKE_CONFIG_EXECUTABLE} --cmake-module-path OUTPUT_VARIABLE CMAKE_MODULE_PATH) + message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") + endif() +endif() + +# needs to have been installed somewhere on CMAKE_MODULE_PATH, +# (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX) +# +include(xo_macros/xo_cxx) + +xo_cxx_bootstrap_message() diff --git a/cmake/xo_numericConfig.cmake.in b/cmake/xo_numericConfig.cmake.in new file mode 100644 index 00000000..4155d92e --- /dev/null +++ b/cmake/xo_numericConfig.cmake.in @@ -0,0 +1,15 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +# note: changes to find_dependency() calls here +# must coordinate with xo_dependency() calls +# in CMakeLists.txt +# +#find_dependency(xo_gc) +find_dependency(xo_facet) +find_dependency(subsys) +#find_dependency(indentlog) + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") +check_required_components("@PROJECT_NAME@") diff --git a/idl/Numeric.json5 b/idl/Numeric.json5 new file mode 100644 index 00000000..4ddcc116 --- /dev/null +++ b/idl/Numeric.json5 @@ -0,0 +1,75 @@ +// can regenerate downstream .*pp files with either: +// cmake --build -- xo-numeric-facet-procedure +// cmake --build -- xo-numeric-genfacet-all + +{ + mode: "facet", + output_cpp_dir: "src/numeric", + output_hpp_dir: "include/xo/numeric", + output_impl_subdir: "detail", + // includes in ASyntaxStateMachine.hpp + includes: [ +// "\"RuntimeContext.hpp\"", +// "", + ], + // extra includes in Procedure.hpp, if any + user_hpp_includes: [ + ], + namespace1: "xo", + namespace2: "scm", + // text after includes, before ASyntaxStateMachine + pretext: [ + //"namespace xo { namespace scm { class ARuntimeContext; } }", + //"namespace xo { namespace scm { class DArray; } }", + ], + facet: "Numeric", + detail_subdir: "detail", + brief: "abstraction for a schematika numeric i.e. something that can participate in arithmetic", + using_doxygen: true, + doc: [ + "Abstraction for a schematika numeric" + ], + types: [ +// { +// name: "AGCObject", +// definition: "xo::mm::AGCObject", +// doc: [ "a gc-aware object" ], +// }, + // { name: string, doc: [ string ], definition: string }, + ], + const_methods: [ +// { +// name: "multiply", +// doc: [ "true iff procedure takes n arguments" ], +// return_type: "bool", +// args: [], +// const: true, +// noexcept: true, +// attributes: [] +// }, +// { +// name: "n_args", +// doc: ["number of arguments. -1 for n-ary" ], +// return_type: "std::int32_t", +// args: [], +// const: true, +// noexcept: true, +// attributes: [] +// } + ], + nonconst_methods: [ +// { +// name: "apply_nocheck", +// doc: ["invoke procedure; assume arguments satisfy type system" ], +// return_type: "obj", +// args: [ +// {type: "obj", name: "rcx"}, +// {type: "const DArray *", name: "args"}, +// ] +// } + ], + router_facet_explicit_content: [ + // this doesn't seem to show up anywhere + "static obj multiply(obj lhs, obj rhs);" + ], +} diff --git a/include/xo/numeric/Numeric.hpp b/include/xo/numeric/Numeric.hpp new file mode 100644 index 00000000..54f97420 --- /dev/null +++ b/include/xo/numeric/Numeric.hpp @@ -0,0 +1,22 @@ +/** @file Numeric.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Numeric.json5] + * 2. jinja2 template for facet .hpp file: + * [facet.hpp.j2] + * 3. idl for facet methods + * [idl/Numeric.json5] + **/ + +#pragma once + +#include "detail/ANumeric.hpp" +#include "detail/INumeric_Any.hpp" +#include "detail/INumeric_Xfer.hpp" +#include "detail/RNumeric.hpp" + + +/* end Numeric.hpp */ diff --git a/include/xo/numeric/NumericDispatch.hpp b/include/xo/numeric/NumericDispatch.hpp new file mode 100644 index 00000000..45f12a75 --- /dev/null +++ b/include/xo/numeric/NumericDispatch.hpp @@ -0,0 +1,20 @@ +/** @file NumericDispatch.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +namespace xo { + namespace scm { + + class NumericDispatch { + public: + + + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end NumericDispatch.hpp */ diff --git a/include/xo/numeric/NumericOps.hpp b/include/xo/numeric/NumericOps.hpp new file mode 100644 index 00000000..720d65db --- /dev/null +++ b/include/xo/numeric/NumericOps.hpp @@ -0,0 +1,44 @@ +/** @file NumericOps.hpp +* + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "Numeric.hpp" + +namespace xo { + namespace scm { + + class INumericOps { + public: + using BinaryOp1 = obj (*)(obj mm, void * x, void * y); + + public: + explicit INumericOp9s(BinaryOp1 multiply) : multiply_{multiply} {} + + /** multiply (x,y); allocate from mm **/ + BinaryOp1 multiply_; + }; + + /** Convenience template. To use, provide implementation + * for + * _multiply() ... + * + **/ + template + class NumericOps : public INumericOps { + public: + using BinaryOp1_Impl = obj (*)(obj mm, DRepr1 * x, DRepr2 * y); + + public: + explicit NumericOps(BinaryOp1_Impl multiply) + : INumericOps(reinterpret_cast(multiply)) + {} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end NumericOps.hpp */ + diff --git a/include/xo/numeric/detail/ANumeric.hpp b/include/xo/numeric/detail/ANumeric.hpp new file mode 100644 index 00000000..bda27456 --- /dev/null +++ b/include/xo/numeric/detail/ANumeric.hpp @@ -0,0 +1,70 @@ +/** @file ANumeric.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Numeric.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [abstract_facet.hpp.j2] + * 3. idl for facet methods + * [idl/Numeric.json5] + **/ + +#pragma once + +// includes (via {facet_includes}) +#include +#include +#include + + +namespace xo { +namespace scm { + +using Copaque = const void *; +using Opaque = void *; + +/** +Abstraction for a schematika numeric +**/ +class ANumeric { +public: + /** @defgroup scm-numeric-type-traits **/ + ///@{ + // types + /** integer identifying a type **/ + using typeseq = xo::facet::typeseq; + using Copaque = const void *; + using Opaque = void *; + ///@} + + /** @defgroup scm-numeric-methods **/ + ///@{ + // const methods + /** RTTI: unique id# for actual runtime data representation **/ + virtual typeseq _typeseq() const noexcept = 0; + /** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/ + virtual void _drop(Opaque d) const noexcept = 0; + + // nonconst methods + ///@} +}; /*ANumeric*/ + +/** Implementation INumeric_DRepr of ANumeric for state DRepr + * should provide a specialization: + * + * template <> + * struct xo::facet::FacetImplementation { + * using Impltype = INumeric_DRepr; + * }; + * + * then INumeric_ImplType --> INumeric_DRepr + **/ +template +using INumeric_ImplType = xo::facet::FacetImplType; + +} /*namespace scm*/ +} /*namespace xo*/ + +/* ANumeric.hpp */ diff --git a/include/xo/numeric/detail/INumeric_Any.hpp b/include/xo/numeric/detail/INumeric_Any.hpp new file mode 100644 index 00000000..0f5a03f2 --- /dev/null +++ b/include/xo/numeric/detail/INumeric_Any.hpp @@ -0,0 +1,87 @@ +/** @file INumeric_Any.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Numeric.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/Numeric.json5] + **/ + +#pragma once + +#include "ANumeric.hpp" +#include + +namespace xo { namespace scm { class INumeric_Any; } } + +namespace xo { +namespace facet { + +template <> +struct FacetImplementation +{ + using ImplType = xo::scm::INumeric_Any; +}; + +} +} + +namespace xo { +namespace scm { + + /** @class INumeric_Any + * @brief ANumeric implementation for empty variant instance + **/ + class INumeric_Any : public ANumeric { + public: + /** @defgroup scm-numeric-any-type-traits **/ + ///@{ + + /** integer identifying a type **/ + using typeseq = xo::facet::typeseq; + + ///@} + /** @defgroup scm-numeric-any-methods **/ + ///@{ + + const ANumeric * iface() const { return std::launder(this); } + + // from ANumeric + + // builtin methods + typeseq _typeseq() const noexcept override { return s_typeseq; } + [[noreturn]] void _drop(Opaque) const noexcept override { _fatal(); } + + // const methods + + // nonconst methods + + ///@} + + private: + /** @defgraoup scm-numeric-any-private-methods **/ + ///@{ + + [[noreturn]] static void _fatal(); + + ///@} + + public: + /** @defgroup scm-numeric-any-member-vars **/ + ///@{ + + static typeseq s_typeseq; + static bool _valid; + + ///@} + }; + +} /*namespace scm */ +} /*namespace xo */ + +/* INumeric_Any.hpp */ diff --git a/include/xo/numeric/detail/INumeric_Xfer.hpp b/include/xo/numeric/detail/INumeric_Xfer.hpp new file mode 100644 index 00000000..c9cd2473 --- /dev/null +++ b/include/xo/numeric/detail/INumeric_Xfer.hpp @@ -0,0 +1,79 @@ +/** @file INumeric_Xfer.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Numeric.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/Numeric.json5] + **/ + +#pragma once + + +namespace xo { +namespace scm { + /** @class INumeric_Xfer + **/ + template + class INumeric_Xfer : public ANumeric { + public: + /** @defgroup scm-numeric-xfer-type-traits **/ + ///@{ + /** actual implementation (not generated; often delegates to DRepr) **/ + using Impl = INumeric_DRepr; + /** integer identifying a type **/ + using typeseq = ANumeric::typeseq; + ///@} + + /** @defgroup scm-numeric-xfer-methods **/ + ///@{ + + static const DRepr & _dcast(Copaque d) { return *(const DRepr *)d; } + static DRepr & _dcast(Opaque d) { return *(DRepr *)d; } + + // from ANumeric + + // builtin methods + typeseq _typeseq() const noexcept override { return s_typeseq; } + void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); } + + // const methods + + // non-const methods + + ///@} + + private: + using I = Impl; + + public: + /** @defgroup scm-numeric-xfer-member-vars **/ + ///@{ + + /** typeseq for template parameter DRepr **/ + static typeseq s_typeseq; + /** true iff satisfies facet implementation **/ + static bool _valid; + + ///@} + }; + + template + xo::facet::typeseq + INumeric_Xfer::s_typeseq + = xo::facet::typeseq::id(); + + template + bool + INumeric_Xfer::_valid + = xo::facet::valid_facet_implementation(); + +} /*namespace scm */ +} /*namespace xo*/ + +/* end INumeric_Xfer.hpp */ diff --git a/include/xo/numeric/detail/RNumeric.hpp b/include/xo/numeric/detail/RNumeric.hpp new file mode 100644 index 00000000..86cac666 --- /dev/null +++ b/include/xo/numeric/detail/RNumeric.hpp @@ -0,0 +1,81 @@ +/** @file RNumeric.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/Numeric.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/Numeric.json5] + **/ + +#pragma once + +#include "ANumeric.hpp" + +namespace xo { +namespace scm { + +/** @class RNumeric + **/ +template +class RNumeric : public Object { +private: + using O = Object; + +public: + /** @defgroup scm-numeric-router-type-traits **/ + ///@{ + using ObjectType = Object; + using DataPtr = Object::DataPtr; + using typeseq = xo::reflect::typeseq; + ///@} + + /** @defgroup scm-numeric-router-ctors **/ + ///@{ + RNumeric() {} + RNumeric(Object::DataPtr data) : Object{std::move(data)} {} + RNumeric(const ANumeric * iface, void * data) + requires std::is_same_v + : Object(iface, data) {} + + ///@} + /** @defgroup scm-numeric-router-methods **/ + ///@{ + + // explicit injected content + + // builtin methods + typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } + void _drop() const noexcept { O::iface()->_drop(O::data()); } + + // const methods + + // non-const methods (still const in router!) + + ///@} + /** @defgroup scm-numeric-member-vars **/ + ///@{ + + static bool _valid; + + ///@} +}; + +template +bool +RNumeric::_valid = xo::facet::valid_object_router(); + +} /*namespace scm*/ +} /*namespace xo*/ + +namespace xo { namespace facet { + template + struct RoutingFor { + using RoutingType = xo::scm::RNumeric; + }; +} } + +/* end RNumeric.hpp */ diff --git a/src/numeric/INumeric_Any.cpp b/src/numeric/INumeric_Any.cpp new file mode 100644 index 00000000..842ae275 --- /dev/null +++ b/src/numeric/INumeric_Any.cpp @@ -0,0 +1,41 @@ +/** @file INumeric_Any.cpp + * + **/ + +#include "detail/INumeric_Any.hpp" +#include + +namespace xo { +namespace scm { + +using xo::facet::DVariantPlaceholder; +using xo::facet::typeseq; +using xo::facet::valid_facet_implementation; + +void +INumeric_Any::_fatal() +{ + /* control here on uninitialized IAllocator_Any. + * Initialized instance will have specific implementation type + */ + std::cerr << "fatal" + << ": attempt to call uninitialized" + << " INumeric_Any method" + << std::endl; + std::terminate(); +} + +typeseq +INumeric_Any::s_typeseq = typeseq::id(); + +bool +INumeric_Any::_valid + = valid_facet_implementation(); + +// nonconst methods + + +} /*namespace scm*/ +} /*namespace xo*/ + +/* end INumeric_Any.cpp */ From ac1395ce98449daafa68505a6d66a61b33d8ce35 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 18 Feb 2026 21:47:02 -0800 Subject: [PATCH 02/32] xo-reader2 stack: + xo-numeric + setup multi dispatch for *,/ --- CMakeLists.txt | 26 +++++- NumericDispatch.hpp | 44 ---------- cmake/xo_numericConfig.cmake.in | 2 +- idl/INumeric_DFloat.json5 | 18 ++++ idl/INumeric_DInteger.json5 | 18 ++++ include/xo/numeric/FloatIntegerOps.hpp | 42 ++++++++++ include/xo/numeric/FloatOps.hpp | 30 +++++++ include/xo/numeric/IntegerOps.hpp | 31 +++++++ include/xo/numeric/NumericDispatch.hpp | 82 ++++++++++++++++++- include/xo/numeric/NumericOps.hpp | 46 ++++++----- include/xo/numeric/NumericPrimitives.hpp | 23 ++++++ include/xo/numeric/float/INumeric_DFloat.hpp | 56 +++++++++++++ include/xo/numeric/init_numeric.hpp | 21 +++++ .../xo/numeric/integer/INumeric_DInteger.hpp | 56 +++++++++++++ .../xo/numeric/numeric_register_facets.hpp | 16 ++++ src/numeric/CMakeLists.txt | 25 ++++++ src/numeric/FloatIntegerOps.cpp | 48 +++++++++++ src/numeric/FloatOps.cpp | 31 +++++++ src/numeric/INumeric_DFloat.cpp | 22 +++++ src/numeric/INumeric_DInteger.cpp | 22 +++++ src/numeric/IntegerOps.cpp | 31 +++++++ src/numeric/NumericDispatch.cpp | 59 +++++++++++++ src/numeric/NumericPrimitives.cpp | 22 +++++ src/numeric/init_numeric.cpp | 36 ++++++++ src/numeric/numeric_register_facets.cpp | 61 ++++++++++++++ utest/CMakeLists.txt | 12 +++ utest/Numeric.test.cpp | 76 +++++++++++++++++ utest/numeric_utest_main.cpp | 24 ++++++ 28 files changed, 911 insertions(+), 69 deletions(-) delete mode 100644 NumericDispatch.hpp create mode 100644 idl/INumeric_DFloat.json5 create mode 100644 idl/INumeric_DInteger.json5 create mode 100644 include/xo/numeric/FloatIntegerOps.hpp create mode 100644 include/xo/numeric/FloatOps.hpp create mode 100644 include/xo/numeric/IntegerOps.hpp create mode 100644 include/xo/numeric/NumericPrimitives.hpp create mode 100644 include/xo/numeric/float/INumeric_DFloat.hpp create mode 100644 include/xo/numeric/init_numeric.hpp create mode 100644 include/xo/numeric/integer/INumeric_DInteger.hpp create mode 100644 include/xo/numeric/numeric_register_facets.hpp create mode 100644 src/numeric/CMakeLists.txt create mode 100644 src/numeric/FloatIntegerOps.cpp create mode 100644 src/numeric/FloatOps.cpp create mode 100644 src/numeric/INumeric_DFloat.cpp create mode 100644 src/numeric/INumeric_DInteger.cpp create mode 100644 src/numeric/IntegerOps.cpp create mode 100644 src/numeric/NumericDispatch.cpp create mode 100644 src/numeric/NumericPrimitives.cpp create mode 100644 src/numeric/init_numeric.cpp create mode 100644 src/numeric/numeric_register_facets.cpp create mode 100644 utest/CMakeLists.txt create mode 100644 utest/Numeric.test.cpp create mode 100644 utest/numeric_utest_main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c762fbfa..92d4b9e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,14 +29,32 @@ xo_add_genfacet( # ---------------------------------------------------------------- +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-numeric-facetimpl-numeric-float + FACET_PKG xo_numeric + FACET Numeric + REPR Float + INPUT idl/INumeric_DFloat.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-numeric-facetimpl-numeric-integer + FACET_PKG xo_numeric + FACET Numeric + REPR Integer + INPUT idl/INumeric_DInteger.json5 +) + +# ---------------------------------------------------------------- + xo_add_genfacet_all(xo-numeric-genfacet-all) # ---------------------------------------------------------------- -#add_subdirectory(src/numeric) # NOTE: will need cmake export here -#add_subdirectory(utest) +add_subdirectory(src/numeric) +add_subdirectory(utest) # ---------------------------------------------------------------- # cmake export - - diff --git a/NumericDispatch.hpp b/NumericDispatch.hpp deleted file mode 100644 index a312c1c1..00000000 --- a/NumericDispatch.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/** @file NumericDispatch.hpp - * - * @author Roland Conybeare, Feb 2026 - **/ - -#pragma once - -//#include // probably will need this at some point? -#include -#include - -namespace xo { - namespace scm { - - /** type-erased arithmetic dispatch. - **/ - struct NumericOps { - obj - }; - - class NumericDispatch { - public: - using KeyType = std::pair; - using MapType = xo::map::DArenaHashMap - - /** combine two typeseq's to get hash value **/ - struct KeyHash { - std::size_t operator()(const key_type & k) const noexcept { - // combine the two seqno values - std::size_t h1 = std::hash{}(k.first.seqno()); - std::size_t h2 = std::hash{}(k.second.seqno()); - return h1 ^ (h2 << 1); - } - }; - - - }; - - } /*namespace scm*/ -} /*namespace xo*/ - -/* end NumericDispqatch.hpp */ - - diff --git a/cmake/xo_numericConfig.cmake.in b/cmake/xo_numericConfig.cmake.in index 4155d92e..a38ab389 100644 --- a/cmake/xo_numericConfig.cmake.in +++ b/cmake/xo_numericConfig.cmake.in @@ -7,7 +7,7 @@ include(CMakeFindDependencyMacro) # in CMakeLists.txt # #find_dependency(xo_gc) -find_dependency(xo_facet) +find_dependency(xo_procedure2) find_dependency(subsys) #find_dependency(indentlog) diff --git a/idl/INumeric_DFloat.json5 b/idl/INumeric_DFloat.json5 new file mode 100644 index 00000000..6b269c6d --- /dev/null +++ b/idl/INumeric_DFloat.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/numeric", + output_hpp_dir: "include/xo/numeric", + output_impl_subdir: "float", + includes: [ +// "", +// "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Numeric.json5", + brief: "provide ANumeric interface for DFloat", + using_doxygen: true, + repr: "DFloat", + doc: [ "implement ANumeric for DFloat" ], +} diff --git a/idl/INumeric_DInteger.json5 b/idl/INumeric_DInteger.json5 new file mode 100644 index 00000000..5c478c12 --- /dev/null +++ b/idl/INumeric_DInteger.json5 @@ -0,0 +1,18 @@ +{ + mode: "implementation", + output_cpp_dir: "src/numeric", + output_hpp_dir: "include/xo/numeric", + output_impl_subdir: "integer", + includes: [ +// "", +// "" + ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Numeric.json5", + brief: "provide ANumeric interface for DInteger", + using_doxygen: true, + repr: "DInteger", + doc: [ "implement ANumeric for DInteger" ], +} diff --git a/include/xo/numeric/FloatIntegerOps.hpp b/include/xo/numeric/FloatIntegerOps.hpp new file mode 100644 index 00000000..97a2c3f6 --- /dev/null +++ b/include/xo/numeric/FloatIntegerOps.hpp @@ -0,0 +1,42 @@ +/** @file FloatIntegerOps.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "Numeric.hpp" +#include +#include +#include + + +namespace xo { + namespace scm { + + class FloatIntegerOps { + public: + using AGCObject = xo::mm::AGCObject; + + public: + static obj multiply(obj rcx, + DFloat * x, DInteger * y); + static obj divide(obj rcx, + DFloat * x, DInteger * y); + }; + + class IntegerFloatOps { + public: + using AGCObject = xo::mm::AGCObject; + + public: + static obj multiply(obj rcx, + DInteger * x, DFloat * y); + static obj divide(obj rcx, + DInteger * x, DFloat * y); + }; + + } +} + +/* end FloatIntegerOps.hpp */ diff --git a/include/xo/numeric/FloatOps.hpp b/include/xo/numeric/FloatOps.hpp new file mode 100644 index 00000000..c3a2c288 --- /dev/null +++ b/include/xo/numeric/FloatOps.hpp @@ -0,0 +1,30 @@ +/** @file FloatOps.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "Numeric.hpp" +#include +#include + + +namespace xo { + namespace scm { + + class FloatOps { + public: + using AGCObject = xo::mm::AGCObject; + + public: + static obj multiply(obj rcx, + DFloat * x, DFloat * y); + static obj divide(obj rcx, + DFloat * x, DFloat * y); + }; + + } +} + +/* end FloatOps.hpp */ diff --git a/include/xo/numeric/IntegerOps.hpp b/include/xo/numeric/IntegerOps.hpp new file mode 100644 index 00000000..4f9138de --- /dev/null +++ b/include/xo/numeric/IntegerOps.hpp @@ -0,0 +1,31 @@ +/** @file IntegerOps.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "Numeric.hpp" +#include +#include + +namespace xo { + namespace scm { + + class IntegerOps { + public: + using AGCObject = xo::mm::AGCObject; + + public: + static obj multiply(obj rcx, + DInteger * x, DInteger * y); + + static obj divide(obj rcx, + DInteger * x, DInteger * y); + + }; + + } +} + +/* end IntegerOps.hpp */ diff --git a/include/xo/numeric/NumericDispatch.hpp b/include/xo/numeric/NumericDispatch.hpp index 45f12a75..5174430e 100644 --- a/include/xo/numeric/NumericDispatch.hpp +++ b/include/xo/numeric/NumericDispatch.hpp @@ -5,13 +5,93 @@ #pragma once +#include "NumericOps.hpp" +#include +#include +#include +#include + namespace xo { namespace scm { + /** Runtime polymoprhic multimethod dispatch. + * Hash on argument types to get function table + **/ class NumericDispatch { public: + //using AAllocator = xo::mm::AAllocator; + using AGCObject = xo::mm::AGCObject; + using MemorySizeVisitor = xo::mm::MemorySizeVisitor; + using typeseq = xo::reflect::typeseq; + using KeyType = std::pair; + using MappedType = AnonymizedNumericOps; - + /** hash function for key_type **/ + struct KeyHash { + + std::size_t operator()(const KeyType & k) const noexcept { + // combine the two seqno values + std::size_t h1 = std::hash{}(k.first.seqno()); + std::size_t h2 = std::hash{}(k.second.seqno()); + + return h1 ^ (h2 << 7); + } + + }; + + using MapType = xo::map::DArenaHashMap>; + + public: + NumericDispatch(uint32_t hint_max_capacity) + : dispatch_{"numeric-dispatch", + hint_max_capacity, + false /*!debug_flag*/} {} + + /** @p hint_max_capacity only honored the first time instance() + * is called. + **/ + static NumericDispatch & instance(uint32_t hint_max_capacity = 64) { + static NumericDispatch s_instance(hint_max_capacity); + return s_instance; + } + + /** multiply w/ runtime polymorphism (double-dispatch) + **/ + static obj multiply(obj rcx, + obj x, + obj y); + + /** divide w/ runtime polymorphism (double-dispatch) + **/ + static obj divide(obj rcx, + obj x, + obj y); + + /** report memory use for owned arenas to @p visitor **/ + void visit_pools(const MemorySizeVisitor & visitor); + + /** Use: + * Need to have overload + * multiply(obj, DRepr1, DRepr2) -> obj + * available + **/ + template + void register_impl(typename NumericOps::BinaryOp_Impl mul_fn, + typename NumericOps::BinaryOp_Impl div_fn) { + + KeyType key(typeseq::id().seqno(), + typeseq::id().seqno()); + + // note: copying op table so they're in proximity + this->dispatch_[key] = NumericOps::make(mul_fn, div_fn); + } + + private: + /** 2d dispatch for arithmetic **/ + MapType dispatch_; }; } /*namespace scm*/ diff --git a/include/xo/numeric/NumericOps.hpp b/include/xo/numeric/NumericOps.hpp index 720d65db..4e900534 100644 --- a/include/xo/numeric/NumericOps.hpp +++ b/include/xo/numeric/NumericOps.hpp @@ -1,44 +1,52 @@ /** @file NumericOps.hpp -* + * * @author Roland Conybeare, Feb 2026 **/ #pragma once -#include "Numeric.hpp" +#include +#include +#include +#include namespace xo { namespace scm { - - class INumericOps { + class AnonymizedNumericOps { public: - using BinaryOp1 = obj (*)(obj mm, void * x, void * y); + using ARuntimeContext = xo::scm::ARuntimeContext; + using AGCObject = xo::mm::AGCObject; + using BinaryOp = obj (*)(obj mm, void * x, void * y); public: - explicit INumericOp9s(BinaryOp1 multiply) : multiply_{multiply} {} + /** note: null ctor load-bearing for membership in DArenaHashTable **/ + AnonymizedNumericOps() = default; + /** @p multiply to multiply (x,y); allocate from mm **/ + explicit AnonymizedNumericOps(BinaryOp multiply, + BinaryOp divide) + : multiply_{multiply}, divide_{divide} {} - /** multiply (x,y); allocate from mm **/ - BinaryOp1 multiply_; + BinaryOp multiply_ = nullptr; + BinaryOp divide_ = nullptr; }; - /** Convenience template. To use, provide implementation - * for - * _multiply() ... - * - **/ template - class NumericOps : public INumericOps { + class NumericOps { public: - using BinaryOp1_Impl = obj (*)(obj mm, DRepr1 * x, DRepr2 * y); + using ARuntimeContext = xo::scm::ARuntimeContext; + using AGCObject = xo::mm::AGCObject; + using BinaryOp_Impl = obj (*)(obj rcx, DRepr1 * x, DRepr2 * y); + using BinaryOp_Anon = AnonymizedNumericOps::BinaryOp; public: - explicit NumericOps(BinaryOp1_Impl multiply) - : INumericOps(reinterpret_cast(multiply)) - {} + static AnonymizedNumericOps make(BinaryOp_Impl multiply, + BinaryOp_Impl divide) { + return AnonymizedNumericOps(reinterpret_cast(multiply), + reinterpret_cast(divide)); + } }; } /*namespace scm*/ } /*namespace xo*/ /* end NumericOps.hpp */ - diff --git a/include/xo/numeric/NumericPrimitives.hpp b/include/xo/numeric/NumericPrimitives.hpp new file mode 100644 index 00000000..376f94b9 --- /dev/null +++ b/include/xo/numeric/NumericPrimitives.hpp @@ -0,0 +1,23 @@ +/** @file NumericDispatch.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include + +namespace xo { + namespace scm { + + /** @brief primitives using multidispatch + **/ + class NumericPrimitives { + public: + /** poly divide **/ + static DPrimitive_gco_2_gco_gco s_div_gco_gco_pm; + }; + } +} + +/* end NumericDispatch.hpp */ diff --git a/include/xo/numeric/float/INumeric_DFloat.hpp b/include/xo/numeric/float/INumeric_DFloat.hpp new file mode 100644 index 00000000..8e88438e --- /dev/null +++ b/include/xo/numeric/float/INumeric_DFloat.hpp @@ -0,0 +1,56 @@ +/** @file INumeric_DFloat.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/INumeric_DFloat.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/INumeric_DFloat.json5] + **/ + +#pragma once + +#include "Numeric.hpp" +#include "DFloat.hpp" + +namespace xo { namespace scm { class INumeric_DFloat; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::INumeric_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class INumeric_DFloat + **/ + class INumeric_DFloat { + public: + /** @defgroup scm-numeric-dfloat-type-traits **/ + ///@{ + using Copaque = xo::scm::ANumeric::Copaque; + using Opaque = xo::scm::ANumeric::Opaque; + ///@} + /** @defgroup scm-numeric-dfloat-methods **/ + ///@{ + // const methods + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/include/xo/numeric/init_numeric.hpp b/include/xo/numeric/init_numeric.hpp new file mode 100644 index 00000000..c3f1cf19 --- /dev/null +++ b/include/xo/numeric/init_numeric.hpp @@ -0,0 +1,21 @@ +/** @file init_numeric.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include + +namespace xo { + /* tag to represent the xo-numeric/ subsystem within ordered initialization */ + enum S_numeric_tag {}; + + template <> + struct InitSubsys { + static void init(); + static InitEvidence require(); + }; +} + +/* end init_numeric.hpp */ diff --git a/include/xo/numeric/integer/INumeric_DInteger.hpp b/include/xo/numeric/integer/INumeric_DInteger.hpp new file mode 100644 index 00000000..ca530949 --- /dev/null +++ b/include/xo/numeric/integer/INumeric_DInteger.hpp @@ -0,0 +1,56 @@ +/** @file INumeric_DInteger.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/INumeric_DInteger.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/INumeric_DInteger.json5] + **/ + +#pragma once + +#include "Numeric.hpp" +#include "DInteger.hpp" + +namespace xo { namespace scm { class INumeric_DInteger; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::INumeric_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class INumeric_DInteger + **/ + class INumeric_DInteger { + public: + /** @defgroup scm-numeric-dinteger-type-traits **/ + ///@{ + using Copaque = xo::scm::ANumeric::Copaque; + using Opaque = xo::scm::ANumeric::Opaque; + ///@} + /** @defgroup scm-numeric-dinteger-methods **/ + ///@{ + // const methods + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/include/xo/numeric/numeric_register_facets.hpp b/include/xo/numeric/numeric_register_facets.hpp new file mode 100644 index 00000000..7beeb10e --- /dev/null +++ b/include/xo/numeric/numeric_register_facets.hpp @@ -0,0 +1,16 @@ +/** @file numeric_register_facets.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +namespace xo { + namespace scm { + /** Setup numeric facet dispatch **/ + bool numeric_register_facets(); + + } +} + +/* end numeric_register_facets.hpp */ diff --git a/src/numeric/CMakeLists.txt b/src/numeric/CMakeLists.txt new file mode 100644 index 00000000..4d2b4345 --- /dev/null +++ b/src/numeric/CMakeLists.txt @@ -0,0 +1,25 @@ +# numeric/CMakeLists.txt + +set(SELF_LIB xo_numeric) +set(SELF_SRCS + init_numeric.cpp + numeric_register_facets.cpp + NumericPrimitives.cpp + NumericDispatch.cpp + INumeric_Any.cpp + FloatIntegerOps.cpp + FloatOps.cpp + IntegerOps.cpp +) + +xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) +xo_dependency(${SELF_LIB} xo_procedure2) +xo_dependency(${SELF_LIB} subsys) + +xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) + +# ---------------------------------------------------------------- +# docs targets depend on other library/utest/exec targets above, +# --> must come after them. +# +#add_subdirectory(docs) diff --git a/src/numeric/FloatIntegerOps.cpp b/src/numeric/FloatIntegerOps.cpp new file mode 100644 index 00000000..65a106ab --- /dev/null +++ b/src/numeric/FloatIntegerOps.cpp @@ -0,0 +1,48 @@ +/** @file FloatIntegerOps.cp + * + * @author Roland Conybeare, Feb 2206 + **/ + +#include "FloatIntegerOps.hpp" +#include "float/INumeric_DFloat.hpp" + +namespace xo { + using xo::mm::AGCObject; + + namespace scm { + + // ----- Float op Integer ----- + + obj + FloatIntegerOps::multiply(obj rcx, + DFloat * x, DInteger * y) + { + return DFloat::box(rcx.allocator(), x->value() * y->value()); + } + + obj + FloatIntegerOps::divide(obj rcx, + DFloat * x, DInteger * y) + { + return DFloat::box(rcx.allocator(), x->value() / y->value()); + } + + // ----- Integer op Float ----- + + obj + IntegerFloatOps::multiply(obj rcx, + DInteger * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), x->value() * y->value()); + } + + obj + IntegerFloatOps::divide(obj rcx, + DInteger * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), x->value() / y->value()); + } + } +} + +/* end FloatIntegerOps.cpp */ diff --git a/src/numeric/FloatOps.cpp b/src/numeric/FloatOps.cpp new file mode 100644 index 00000000..9db149b9 --- /dev/null +++ b/src/numeric/FloatOps.cpp @@ -0,0 +1,31 @@ +/** @file FloatOps.cp + * + * @author Roland Conybeare, Feb 2206 + **/ + +#include "FloatOps.hpp" +#include "float/INumeric_DFloat.hpp" + +namespace xo { + using xo::mm::AGCObject; + + namespace scm { + + obj + FloatOps::multiply(obj rcx, + DFloat * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), x->value() * y->value()); + } + + obj + FloatOps::divide(obj rcx, + DFloat * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), x->value() / y->value()); + } + + } +} + +/* end FloatOps.cpp */ diff --git a/src/numeric/INumeric_DFloat.cpp b/src/numeric/INumeric_DFloat.cpp new file mode 100644 index 00000000..4024dc04 --- /dev/null +++ b/src/numeric/INumeric_DFloat.cpp @@ -0,0 +1,22 @@ +/** @file INumeric_DFloat.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/INumeric_DFloat.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/INumeric_DFloat.json5] +**/ + +#include "float/INumeric_DFloat.hpp" + +namespace xo { + namespace scm { + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end INumeric_DFloat.cpp */ diff --git a/src/numeric/INumeric_DInteger.cpp b/src/numeric/INumeric_DInteger.cpp new file mode 100644 index 00000000..a4ae6a12 --- /dev/null +++ b/src/numeric/INumeric_DInteger.cpp @@ -0,0 +1,22 @@ +/** @file INumeric_DInteger.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/INumeric_DInteger.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/INumeric_DInteger.json5] +**/ + +#include "integer/INumeric_DInteger.hpp" + +namespace xo { + namespace scm { + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end INumeric_DInteger.cpp */ diff --git a/src/numeric/IntegerOps.cpp b/src/numeric/IntegerOps.cpp new file mode 100644 index 00000000..c8322266 --- /dev/null +++ b/src/numeric/IntegerOps.cpp @@ -0,0 +1,31 @@ +/** @file IntegerOps.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "IntegerOps.hpp" +#include "integer/INumeric_DInteger.hpp" + +namespace xo { + using xo::mm::AGCObject; + + namespace scm { + + obj + IntegerOps::multiply(obj rcx, + DInteger * x, DInteger * y) + { + return DInteger::box(rcx.allocator(), x->value() * y->value()); + } + + obj + IntegerOps::divide(obj rcx, + DInteger * x, DInteger * y) + { + return DInteger::box(rcx.allocator(), x->value() / y->value()); + } + + } +} + +/* end IntegerOps.cpp */ diff --git a/src/numeric/NumericDispatch.cpp b/src/numeric/NumericDispatch.cpp new file mode 100644 index 00000000..bfc65586 --- /dev/null +++ b/src/numeric/NumericDispatch.cpp @@ -0,0 +1,59 @@ +/** @file NumericDispatch.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "NumericDispatch.hpp" +#include + +namespace xo { + using xo::mm::AGCObject; + + namespace scm { + + void + NumericDispatch::visit_pools(const MemorySizeVisitor & visitor) + { + dispatch_.visit_pools(visitor); + } + + obj + NumericDispatch::multiply(obj rcx, + obj x, + obj y) + { + KeyType key(x._typeseq(), y._typeseq()); + + auto target_fn + = NumericDispatch::instance().dispatch_[key].multiply_; + + return (*target_fn)(rcx, x.data(), y.data()); + } + + obj + NumericDispatch::divide(obj rcx, + obj x, + obj y) + { + scope log(XO_DEBUG(true)); + + KeyType key(x._typeseq(), y._typeseq()); + + log && log(xtag("x.tseq", x._typeseq().seqno()), + xtag("y.tseq", y._typeseq().seqno())); + + auto target_fn + = NumericDispatch::instance().dispatch_[key].divide_; + + log && log(xtag("target_fn", target_fn)); + + assert(target_fn); + + return (*target_fn)(rcx, x.data(), y.data()); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end NumericDispatch.cpp **/ diff --git a/src/numeric/NumericPrimitives.cpp b/src/numeric/NumericPrimitives.cpp new file mode 100644 index 00000000..5666a751 --- /dev/null +++ b/src/numeric/NumericPrimitives.cpp @@ -0,0 +1,22 @@ +/** @file NumericPrimitives.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "NumericPrimitives.hpp" +#include "NumericDispatch.hpp" + +namespace xo { + using xo::mm::AGCObject; + + namespace scm { + + DPrimitive_gco_2_gco_gco + NumericPrimitives::s_div_gco_gco_pm("_div", + &NumericDispatch::divide); + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end NumericDispatch.cpp */ diff --git a/src/numeric/init_numeric.cpp b/src/numeric/init_numeric.cpp new file mode 100644 index 00000000..1b205585 --- /dev/null +++ b/src/numeric/init_numeric.cpp @@ -0,0 +1,36 @@ +/** @file init_numeric.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "init_numeric.hpp" +#include +#include "Subsystem.hpp" +#include "numeric_register_facets.hpp" + +namespace xo { + using xo::scm::numeric_register_facets; + + void + InitSubsys::init() + { + numeric_register_facets(); + } + + InitEvidence + InitSubsys::require() + { + InitEvidence retval; + + /* direct subsystem deps for xo-numeric/ */ + retval ^= InitSubsys::require(); + + /* xo-numeric/'s own initialization code */ + retval ^= Subsystem::provide("numeric", &init); + + return retval; + } + +} /*namespace xo*/ + +/* end init_numeric.cpp */ diff --git a/src/numeric/numeric_register_facets.cpp b/src/numeric/numeric_register_facets.cpp new file mode 100644 index 00000000..3e2d94a5 --- /dev/null +++ b/src/numeric/numeric_register_facets.cpp @@ -0,0 +1,61 @@ +/** @file numeric_register_facets.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "numeric_register_facets.hpp" +#include "NumericDispatch.hpp" +#include "Numeric.hpp" + +#include "FloatIntegerOps.hpp" +#include "FloatOps.hpp" +#include "float/INumeric_DFloat.hpp" + +#include "IntegerOps.hpp" +#include "integer/INumeric_DInteger.hpp" + +#include +#include + +#include +#include +#include + +namespace xo { + using xo::facet::FacetRegistry; + using xo::reflect::typeseq; + + namespace scm { + + bool + numeric_register_facets() + { + scope log(XO_DEBUG(true)); + + FacetRegistry::register_impl(); + + NumericDispatch::instance().register_impl + (&FloatOps::multiply, + &FloatOps::divide); + + NumericDispatch::instance().register_impl + (&FloatIntegerOps::multiply, + &FloatIntegerOps::divide); + + NumericDispatch::instance().register_impl + (&IntegerFloatOps::multiply, + &IntegerFloatOps::divide); + + NumericDispatch::instance().register_impl + (&IntegerOps::multiply, + &IntegerOps::divide); + + log && log(xtag("ANumeric.tseq", typeseq::id())); + + return true; + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end numeric_register_facets.cpp */ diff --git a/utest/CMakeLists.txt b/utest/CMakeLists.txt new file mode 100644 index 00000000..8b714e4a --- /dev/null +++ b/utest/CMakeLists.txt @@ -0,0 +1,12 @@ +# built unittest xo-numeric/utest + +set(UTEST_EXE utest.numeric) +set(UTEST_SRCS + numeric_utest_main.cpp + Numeric.test.cpp +) + +xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS}) +xo_self_dependency(${UTEST_EXE} xo_numeric) +#xo_dependency(${UTEST_EXE} randomgen) +xo_external_target_dependency(${UTEST_EXE} Catch2 Catch2::Catch2) diff --git a/utest/Numeric.test.cpp b/utest/Numeric.test.cpp new file mode 100644 index 00000000..53a44058 --- /dev/null +++ b/utest/Numeric.test.cpp @@ -0,0 +1,76 @@ +/** @file Numeric.test.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "init_numeric.hpp" +#include "NumericDispatch.hpp" +#include +#include +#include + +namespace xo { + using xo::scm::NumericDispatch; + //using xo::mm::AAllocator; + using xo::mm::DArena; + using xo::mm::ArenaConfig;; + using xo::mm::MemorySizeInfo; + using xo::facet::FacetRegistry; + using xo::facet::TypeRegistry; + //using xo::facet::with_facet; + //using xo::facet::obj; + + namespace ut { + + namespace { + struct Fixture { + explicit Fixture(const std::string & testname, + std::size_t aux_arena_size = 16 * 1024) + : aux_arena_( + ArenaConfig().with_name(testname).with_size(aux_arena_size)) + {} + + + bool log_memory_layout(scope * p_log) { + auto visitor = [p_log](const MemorySizeInfo & info) { + *p_log && (*p_log)(xtag("resource", info.resource_name_), + xtag("used", info.used_), + xtag("alloc", info.allocated_), + xtag("commit", info.committed_), + xtag("resv", info.reserved_)); + }; + + aux_arena_.visit_pools(visitor); + TypeRegistry::instance().visit_pools(visitor); + FacetRegistry::instance().visit_pools(visitor); + NumericDispatch::instance().visit_pools(visitor); + + return true; + } + + DArena aux_arena_; + }; + } /*namespace*/ + + static InitEvidence s_init = (InitSubsys::require()); + + TEST_CASE("Numeric-init" "[numeric]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + Fixture fixture(testname); + { + // real purpose: ensure s_init sutvives static linking + REQUIRE(s_init.evidence()); + } + + log && fixture.log_memory_layout(&log); + } + + } /*namespace ut*/ +} /*namespace xo*/ + +/* end Numeric.test.cpp */ diff --git a/utest/numeric_utest_main.cpp b/utest/numeric_utest_main.cpp new file mode 100644 index 00000000..96d5d0b6 --- /dev/null +++ b/utest/numeric_utest_main.cpp @@ -0,0 +1,24 @@ +/* file numeric_utest_main.cpp */ + +#include + +#define CATCH_CONFIG_RUNNER +#include "catch2/catch.hpp" + +int +main(int argc, char* argv[]) +{ + using xo::Subsystem; + + // Your custom initialization code here + Subsystem::initialize_all(); + + // Run Catch2's test session + int result = Catch::Session().run(argc, argv); + + // cleanup here, if any + + return result; +} + +/* end numeric_utest_main.cpp */ From 43f120dd107c978bb9b003f3200837b467d460cd Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 18 Feb 2026 22:00:30 -0800 Subject: [PATCH 03/32] xo-interpreter2 stack: use xo-numeric/ to support op* --- include/xo/numeric/NumericPrimitives.hpp | 4 +++- src/numeric/NumericPrimitives.cpp | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/xo/numeric/NumericPrimitives.hpp b/include/xo/numeric/NumericPrimitives.hpp index 376f94b9..3eab681a 100644 --- a/include/xo/numeric/NumericPrimitives.hpp +++ b/include/xo/numeric/NumericPrimitives.hpp @@ -14,7 +14,9 @@ namespace xo { **/ class NumericPrimitives { public: - /** poly divide **/ + /** polymorphic (in both arguments) multiply **/ + static DPrimitive_gco_2_gco_gco s_mul_gco_gco_pm; + /** polymorphic (in both arguments) divide **/ static DPrimitive_gco_2_gco_gco s_div_gco_gco_pm; }; } diff --git a/src/numeric/NumericPrimitives.cpp b/src/numeric/NumericPrimitives.cpp index 5666a751..a17de848 100644 --- a/src/numeric/NumericPrimitives.cpp +++ b/src/numeric/NumericPrimitives.cpp @@ -11,6 +11,10 @@ namespace xo { namespace scm { + DPrimitive_gco_2_gco_gco + NumericPrimitives::s_mul_gco_gco_pm("_mul", + &NumericDispatch::multiply); + DPrimitive_gco_2_gco_gco NumericPrimitives::s_div_gco_gco_pm("_div", &NumericDispatch::divide); From 9dca9a8c46da1aa911d2d823e38a7a54a1e63980 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 18 Feb 2026 22:40:37 -0800 Subject: [PATCH 04/32] xo-reader2 stack: use NumericDispatch for *,/,+,- ops --- include/xo/numeric/FloatIntegerOps.hpp | 8 +++++ include/xo/numeric/FloatOps.hpp | 4 +++ include/xo/numeric/IntegerOps.hpp | 6 ++++ include/xo/numeric/NumericDispatch.hpp | 22 ++++++++++-- include/xo/numeric/NumericOps.hpp | 16 ++++++--- include/xo/numeric/NumericPrimitives.hpp | 4 +++ src/numeric/FloatIntegerOps.cpp | 29 ++++++++++++++++ src/numeric/FloatOps.cpp | 15 ++++++++ src/numeric/IntegerOps.cpp | 14 ++++++++ src/numeric/NumericDispatch.cpp | 44 +++++++++++++++++++----- src/numeric/NumericPrimitives.cpp | 8 +++++ src/numeric/numeric_register_facets.cpp | 16 ++++++--- 12 files changed, 168 insertions(+), 18 deletions(-) diff --git a/include/xo/numeric/FloatIntegerOps.hpp b/include/xo/numeric/FloatIntegerOps.hpp index 97a2c3f6..9d21540f 100644 --- a/include/xo/numeric/FloatIntegerOps.hpp +++ b/include/xo/numeric/FloatIntegerOps.hpp @@ -23,6 +23,10 @@ namespace xo { DFloat * x, DInteger * y); static obj divide(obj rcx, DFloat * x, DInteger * y); + static obj add(obj rcx, + DFloat * x, DInteger * y); + static obj subtract(obj rcx, + DFloat * x, DInteger * y); }; class IntegerFloatOps { @@ -34,6 +38,10 @@ namespace xo { DInteger * x, DFloat * y); static obj divide(obj rcx, DInteger * x, DFloat * y); + static obj add(obj rcx, + DInteger * x, DFloat * y); + static obj subtract(obj rcx, + DInteger * x, DFloat * y); }; } diff --git a/include/xo/numeric/FloatOps.hpp b/include/xo/numeric/FloatOps.hpp index c3a2c288..75ffb5e4 100644 --- a/include/xo/numeric/FloatOps.hpp +++ b/include/xo/numeric/FloatOps.hpp @@ -22,6 +22,10 @@ namespace xo { DFloat * x, DFloat * y); static obj divide(obj rcx, DFloat * x, DFloat * y); + static obj add(obj rcx, + DFloat * x, DFloat * y); + static obj subtract(obj rcx, + DFloat * x, DFloat * y); }; } diff --git a/include/xo/numeric/IntegerOps.hpp b/include/xo/numeric/IntegerOps.hpp index 4f9138de..d839ad36 100644 --- a/include/xo/numeric/IntegerOps.hpp +++ b/include/xo/numeric/IntegerOps.hpp @@ -23,6 +23,12 @@ namespace xo { static obj divide(obj rcx, DInteger * x, DInteger * y); + static obj add(obj rcx, + DInteger * x, DInteger * y); + + static obj subtract(obj rcx, + DInteger * x, DInteger * y); + }; } diff --git a/include/xo/numeric/NumericDispatch.hpp b/include/xo/numeric/NumericDispatch.hpp index 5174430e..0f7a4ffd 100644 --- a/include/xo/numeric/NumericDispatch.hpp +++ b/include/xo/numeric/NumericDispatch.hpp @@ -70,6 +70,18 @@ namespace xo { obj x, obj y); + /** add w/ runtime polymorphism (double-dispatch) + **/ + static obj add(obj rcx, + obj x, + obj y); + + /** subtract w/ runtime polymorphism (double-dispatch) + **/ + static obj subtract(obj rcx, + obj x, + obj y); + /** report memory use for owned arenas to @p visitor **/ void visit_pools(const MemorySizeVisitor & visitor); @@ -80,13 +92,19 @@ namespace xo { **/ template void register_impl(typename NumericOps::BinaryOp_Impl mul_fn, - typename NumericOps::BinaryOp_Impl div_fn) { + typename NumericOps::BinaryOp_Impl div_fn, + typename NumericOps::BinaryOp_Impl add_fn, + typename NumericOps::BinaryOp_Impl sub_fn) { KeyType key(typeseq::id().seqno(), typeseq::id().seqno()); // note: copying op table so they're in proximity - this->dispatch_[key] = NumericOps::make(mul_fn, div_fn); + this->dispatch_[key] + = NumericOps::make(mul_fn, + div_fn, + add_fn, + sub_fn); } private: diff --git a/include/xo/numeric/NumericOps.hpp b/include/xo/numeric/NumericOps.hpp index 4e900534..bc8630a6 100644 --- a/include/xo/numeric/NumericOps.hpp +++ b/include/xo/numeric/NumericOps.hpp @@ -23,11 +23,15 @@ namespace xo { AnonymizedNumericOps() = default; /** @p multiply to multiply (x,y); allocate from mm **/ explicit AnonymizedNumericOps(BinaryOp multiply, - BinaryOp divide) - : multiply_{multiply}, divide_{divide} {} + BinaryOp divide, + BinaryOp add, + BinaryOp subtract) + : multiply_{multiply}, divide_{divide}, add_{add}, subtract_{subtract} {} BinaryOp multiply_ = nullptr; BinaryOp divide_ = nullptr; + BinaryOp add_ = nullptr; + BinaryOp subtract_ = nullptr; }; template @@ -40,9 +44,13 @@ namespace xo { public: static AnonymizedNumericOps make(BinaryOp_Impl multiply, - BinaryOp_Impl divide) { + BinaryOp_Impl divide, + BinaryOp_Impl add, + BinaryOp_Impl subtract) { return AnonymizedNumericOps(reinterpret_cast(multiply), - reinterpret_cast(divide)); + reinterpret_cast(divide), + reinterpret_cast(add), + reinterpret_cast(subtract)); } }; diff --git a/include/xo/numeric/NumericPrimitives.hpp b/include/xo/numeric/NumericPrimitives.hpp index 3eab681a..f5ce374e 100644 --- a/include/xo/numeric/NumericPrimitives.hpp +++ b/include/xo/numeric/NumericPrimitives.hpp @@ -18,6 +18,10 @@ namespace xo { static DPrimitive_gco_2_gco_gco s_mul_gco_gco_pm; /** polymorphic (in both arguments) divide **/ static DPrimitive_gco_2_gco_gco s_div_gco_gco_pm; + /** polymorphic (in both arguments) add **/ + static DPrimitive_gco_2_gco_gco s_add_gco_gco_pm; + /** polymorphic (in both arguments) subtract **/ + static DPrimitive_gco_2_gco_gco s_sub_gco_gco_pm; }; } } diff --git a/src/numeric/FloatIntegerOps.cpp b/src/numeric/FloatIntegerOps.cpp index 65a106ab..5b15d5bb 100644 --- a/src/numeric/FloatIntegerOps.cpp +++ b/src/numeric/FloatIntegerOps.cpp @@ -27,6 +27,20 @@ namespace xo { return DFloat::box(rcx.allocator(), x->value() / y->value()); } + obj + FloatIntegerOps::add(obj rcx, + DFloat * x, DInteger * y) + { + return DFloat::box(rcx.allocator(), x->value() + y->value()); + } + + obj + FloatIntegerOps::subtract(obj rcx, + DFloat * x, DInteger * y) + { + return DFloat::box(rcx.allocator(), x->value() - y->value()); + } + // ----- Integer op Float ----- obj @@ -42,6 +56,21 @@ namespace xo { { return DFloat::box(rcx.allocator(), x->value() / y->value()); } + + obj + IntegerFloatOps::add(obj rcx, + DInteger * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), x->value() + y->value()); + } + + obj + IntegerFloatOps::subtract(obj rcx, + DInteger * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), x->value() - y->value()); + } + } } diff --git a/src/numeric/FloatOps.cpp b/src/numeric/FloatOps.cpp index 9db149b9..8821e48e 100644 --- a/src/numeric/FloatOps.cpp +++ b/src/numeric/FloatOps.cpp @@ -25,6 +25,21 @@ namespace xo { return DFloat::box(rcx.allocator(), x->value() / y->value()); } + obj + FloatOps::add(obj rcx, + DFloat * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), x->value() + y->value()); + } + + obj + FloatOps::subtract(obj rcx, + DFloat * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), x->value() - y->value()); + } + + } } diff --git a/src/numeric/IntegerOps.cpp b/src/numeric/IntegerOps.cpp index c8322266..0f435b74 100644 --- a/src/numeric/IntegerOps.cpp +++ b/src/numeric/IntegerOps.cpp @@ -25,6 +25,20 @@ namespace xo { return DInteger::box(rcx.allocator(), x->value() / y->value()); } + obj + IntegerOps::add(obj rcx, + DInteger * x, DInteger * y) + { + return DInteger::box(rcx.allocator(), x->value() + y->value()); + } + + obj + IntegerOps::subtract(obj rcx, + DInteger * x, DInteger * y) + { + return DInteger::box(rcx.allocator(), x->value() - y->value()); + } + } } diff --git a/src/numeric/NumericDispatch.cpp b/src/numeric/NumericDispatch.cpp index bfc65586..ded8c420 100644 --- a/src/numeric/NumericDispatch.cpp +++ b/src/numeric/NumericDispatch.cpp @@ -27,6 +27,9 @@ namespace xo { auto target_fn = NumericDispatch::instance().dispatch_[key].multiply_; + if (!target_fn) + assert(false); + return (*target_fn)(rcx, x.data(), y.data()); } @@ -35,23 +38,48 @@ namespace xo { obj x, obj y) { - scope log(XO_DEBUG(true)); - KeyType key(x._typeseq(), y._typeseq()); - log && log(xtag("x.tseq", x._typeseq().seqno()), - xtag("y.tseq", y._typeseq().seqno())); - auto target_fn = NumericDispatch::instance().dispatch_[key].divide_; - log && log(xtag("target_fn", target_fn)); - - assert(target_fn); + if (!target_fn) + assert(false); return (*target_fn)(rcx, x.data(), y.data()); } + obj + NumericDispatch::add(obj rcx, + obj x, + obj y) + { + KeyType key(x._typeseq(), y._typeseq()); + + auto target_fn + = NumericDispatch::instance().dispatch_[key].add_; + + if (!target_fn) + assert(false); + + return (*target_fn)(rcx, x.data(), y.data()); + } + + obj + NumericDispatch::subtract(obj rcx, + obj x, + obj y) + { + KeyType key(x._typeseq(), y._typeseq()); + + auto target_fn + = NumericDispatch::instance().dispatch_[key].subtract_; + + if (!target_fn) + assert(false); + + return (*target_fn)(rcx, x.data(), y.data()); + } } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/numeric/NumericPrimitives.cpp b/src/numeric/NumericPrimitives.cpp index a17de848..ebbcb30b 100644 --- a/src/numeric/NumericPrimitives.cpp +++ b/src/numeric/NumericPrimitives.cpp @@ -19,6 +19,14 @@ namespace xo { NumericPrimitives::s_div_gco_gco_pm("_div", &NumericDispatch::divide); + DPrimitive_gco_2_gco_gco + NumericPrimitives::s_add_gco_gco_pm("_add", + &NumericDispatch::add); + + DPrimitive_gco_2_gco_gco + NumericPrimitives::s_sub_gco_gco_pm("_sub", + &NumericDispatch::subtract); + } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/numeric/numeric_register_facets.cpp b/src/numeric/numeric_register_facets.cpp index 3e2d94a5..20e2093d 100644 --- a/src/numeric/numeric_register_facets.cpp +++ b/src/numeric/numeric_register_facets.cpp @@ -36,19 +36,27 @@ namespace xo { NumericDispatch::instance().register_impl (&FloatOps::multiply, - &FloatOps::divide); + &FloatOps::divide, + &FloatOps::add, + &FloatOps::subtract); NumericDispatch::instance().register_impl (&FloatIntegerOps::multiply, - &FloatIntegerOps::divide); + &FloatIntegerOps::divide, + &FloatIntegerOps::add, + &FloatIntegerOps::subtract); NumericDispatch::instance().register_impl (&IntegerFloatOps::multiply, - &IntegerFloatOps::divide); + &IntegerFloatOps::divide, + &IntegerFloatOps::add, + &IntegerFloatOps::subtract); NumericDispatch::instance().register_impl (&IntegerOps::multiply, - &IntegerOps::divide); + &IntegerOps::divide, + &IntegerOps::add, + &IntegerOps::subtract); log && log(xtag("ANumeric.tseq", typeseq::id())); From 243ad12869197754647508614862da40136a5346 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 19 Feb 2026 09:03:02 -0800 Subject: [PATCH 05/32] xo-interpreter2 stack: streamline op== impl + utests --- include/xo/numeric/FloatIntegerOps.hpp | 6 ++++++ include/xo/numeric/FloatOps.hpp | 3 +++ include/xo/numeric/IntegerOps.hpp | 3 +++ include/xo/numeric/NumericDispatch.hpp | 11 +++++++++-- include/xo/numeric/NumericOps.hpp | 15 +++++++++++---- include/xo/numeric/NumericPrimitives.hpp | 3 +++ src/numeric/FloatIntegerOps.cpp | 17 +++++++++++++++++ src/numeric/FloatOps.cpp | 8 ++++++++ src/numeric/IntegerOps.cpp | 9 +++++++++ src/numeric/NumericDispatch.cpp | 16 ++++++++++++++++ src/numeric/NumericPrimitives.cpp | 4 ++++ src/numeric/numeric_register_facets.cpp | 12 ++++++++---- 12 files changed, 97 insertions(+), 10 deletions(-) diff --git a/include/xo/numeric/FloatIntegerOps.hpp b/include/xo/numeric/FloatIntegerOps.hpp index 9d21540f..5cf301ad 100644 --- a/include/xo/numeric/FloatIntegerOps.hpp +++ b/include/xo/numeric/FloatIntegerOps.hpp @@ -27,6 +27,9 @@ namespace xo { DFloat * x, DInteger * y); static obj subtract(obj rcx, DFloat * x, DInteger * y); + + static obj cmp_equal(obj rcx, + DFloat * x, DInteger * y); }; class IntegerFloatOps { @@ -42,6 +45,9 @@ namespace xo { DInteger * x, DFloat * y); static obj subtract(obj rcx, DInteger * x, DFloat * y); + + static obj cmp_equal(obj rcx, + DInteger * x, DFloat * y); }; } diff --git a/include/xo/numeric/FloatOps.hpp b/include/xo/numeric/FloatOps.hpp index 75ffb5e4..5f7d06be 100644 --- a/include/xo/numeric/FloatOps.hpp +++ b/include/xo/numeric/FloatOps.hpp @@ -26,6 +26,9 @@ namespace xo { DFloat * x, DFloat * y); static obj subtract(obj rcx, DFloat * x, DFloat * y); + + static obj cmp_equal(obj rcx, + DFloat * x, DFloat * y); }; } diff --git a/include/xo/numeric/IntegerOps.hpp b/include/xo/numeric/IntegerOps.hpp index d839ad36..001a915f 100644 --- a/include/xo/numeric/IntegerOps.hpp +++ b/include/xo/numeric/IntegerOps.hpp @@ -29,6 +29,9 @@ namespace xo { static obj subtract(obj rcx, DInteger * x, DInteger * y); + static obj cmp_equal(obj rcx, + DInteger * x, DInteger * y); + }; } diff --git a/include/xo/numeric/NumericDispatch.hpp b/include/xo/numeric/NumericDispatch.hpp index 0f7a4ffd..58d06565 100644 --- a/include/xo/numeric/NumericDispatch.hpp +++ b/include/xo/numeric/NumericDispatch.hpp @@ -82,6 +82,11 @@ namespace xo { obj x, obj y); + /** compare two numeric values for equality **/ + static obj cmp_equal(obj rcx, + obj x, + obj y); + /** report memory use for owned arenas to @p visitor **/ void visit_pools(const MemorySizeVisitor & visitor); @@ -94,7 +99,8 @@ namespace xo { void register_impl(typename NumericOps::BinaryOp_Impl mul_fn, typename NumericOps::BinaryOp_Impl div_fn, typename NumericOps::BinaryOp_Impl add_fn, - typename NumericOps::BinaryOp_Impl sub_fn) { + typename NumericOps::BinaryOp_Impl sub_fn, + typename NumericOps::BinaryOp_Impl cmpeq_fn) { KeyType key(typeseq::id().seqno(), typeseq::id().seqno()); @@ -104,7 +110,8 @@ namespace xo { = NumericOps::make(mul_fn, div_fn, add_fn, - sub_fn); + sub_fn, + cmpeq_fn); } private: diff --git a/include/xo/numeric/NumericOps.hpp b/include/xo/numeric/NumericOps.hpp index bc8630a6..f85b20f4 100644 --- a/include/xo/numeric/NumericOps.hpp +++ b/include/xo/numeric/NumericOps.hpp @@ -25,13 +25,18 @@ namespace xo { explicit AnonymizedNumericOps(BinaryOp multiply, BinaryOp divide, BinaryOp add, - BinaryOp subtract) - : multiply_{multiply}, divide_{divide}, add_{add}, subtract_{subtract} {} + BinaryOp subtract, + BinaryOp cmpeq) + : multiply_{multiply}, divide_{divide}, add_{add}, subtract_{subtract}, + cmpeq_{cmpeq} {} BinaryOp multiply_ = nullptr; BinaryOp divide_ = nullptr; BinaryOp add_ = nullptr; BinaryOp subtract_ = nullptr; + + /** compare numerics for equality **/ + BinaryOp cmpeq_ = nullptr; }; template @@ -46,11 +51,13 @@ namespace xo { static AnonymizedNumericOps make(BinaryOp_Impl multiply, BinaryOp_Impl divide, BinaryOp_Impl add, - BinaryOp_Impl subtract) { + BinaryOp_Impl subtract, + BinaryOp_Impl cmpeq) { return AnonymizedNumericOps(reinterpret_cast(multiply), reinterpret_cast(divide), reinterpret_cast(add), - reinterpret_cast(subtract)); + reinterpret_cast(subtract), + reinterpret_cast(cmpeq)); } }; diff --git a/include/xo/numeric/NumericPrimitives.hpp b/include/xo/numeric/NumericPrimitives.hpp index f5ce374e..8f9c40db 100644 --- a/include/xo/numeric/NumericPrimitives.hpp +++ b/include/xo/numeric/NumericPrimitives.hpp @@ -22,6 +22,9 @@ namespace xo { static DPrimitive_gco_2_gco_gco s_add_gco_gco_pm; /** polymorphic (in both arguments) subtract **/ static DPrimitive_gco_2_gco_gco s_sub_gco_gco_pm; + + /** polymorphic (in both arguments) compare (==) **/ + static DPrimitive_gco_2_gco_gco s_cmpeq_gco_gco_pm; }; } } diff --git a/src/numeric/FloatIntegerOps.cpp b/src/numeric/FloatIntegerOps.cpp index 5b15d5bb..476a6745 100644 --- a/src/numeric/FloatIntegerOps.cpp +++ b/src/numeric/FloatIntegerOps.cpp @@ -5,6 +5,7 @@ #include "FloatIntegerOps.hpp" #include "float/INumeric_DFloat.hpp" +#include namespace xo { using xo::mm::AGCObject; @@ -41,6 +42,14 @@ namespace xo { return DFloat::box(rcx.allocator(), x->value() - y->value()); } + obj + FloatIntegerOps::cmp_equal(obj rcx, + DFloat * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), + x->value() == DFloat::value_type(y->value())); + } + // ----- Integer op Float ----- obj @@ -71,6 +80,14 @@ namespace xo { return DFloat::box(rcx.allocator(), x->value() - y->value()); } + obj + IntegerFloatOps::cmp_equal(obj rcx, + DInteger * x, DFloat * y) + { + return DFloat::box(rcx.allocator(), + DFloat::value_type(x->value() == y->value())); + } + } } diff --git a/src/numeric/FloatOps.cpp b/src/numeric/FloatOps.cpp index 8821e48e..d0aa57aa 100644 --- a/src/numeric/FloatOps.cpp +++ b/src/numeric/FloatOps.cpp @@ -5,6 +5,7 @@ #include "FloatOps.hpp" #include "float/INumeric_DFloat.hpp" +#include namespace xo { using xo::mm::AGCObject; @@ -39,6 +40,13 @@ namespace xo { return DFloat::box(rcx.allocator(), x->value() - y->value()); } + obj + FloatOps::cmp_equal(obj rcx, + DFloat * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), x->value() == y->value()); + } + } } diff --git a/src/numeric/IntegerOps.cpp b/src/numeric/IntegerOps.cpp index 0f435b74..062cbeef 100644 --- a/src/numeric/IntegerOps.cpp +++ b/src/numeric/IntegerOps.cpp @@ -5,8 +5,10 @@ #include "IntegerOps.hpp" #include "integer/INumeric_DInteger.hpp" +#include namespace xo { + using xo::scm::DBoolean; using xo::mm::AGCObject; namespace scm { @@ -39,6 +41,13 @@ namespace xo { return DInteger::box(rcx.allocator(), x->value() - y->value()); } + obj + IntegerOps::cmp_equal(obj rcx, + DInteger * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), x->value() == y->value()); + } + } } diff --git a/src/numeric/NumericDispatch.cpp b/src/numeric/NumericDispatch.cpp index ded8c420..935d92eb 100644 --- a/src/numeric/NumericDispatch.cpp +++ b/src/numeric/NumericDispatch.cpp @@ -81,6 +81,22 @@ namespace xo { return (*target_fn)(rcx, x.data(), y.data()); } + obj + NumericDispatch::cmp_equal(obj rcx, + obj x, + obj y) + { + KeyType key(x._typeseq(), y._typeseq()); + + auto target_fn + = NumericDispatch::instance().dispatch_[key].cmpeq_; + + if (!target_fn) + assert(false); + + return (*target_fn)(rcx, x.data(), y.data()); + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/numeric/NumericPrimitives.cpp b/src/numeric/NumericPrimitives.cpp index ebbcb30b..28031fac 100644 --- a/src/numeric/NumericPrimitives.cpp +++ b/src/numeric/NumericPrimitives.cpp @@ -27,6 +27,10 @@ namespace xo { NumericPrimitives::s_sub_gco_gco_pm("_sub", &NumericDispatch::subtract); + DPrimitive_gco_2_gco_gco + NumericPrimitives::s_cmpeq_gco_gco_pm("_cmpeq", + &NumericDispatch::cmp_equal); + } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/numeric/numeric_register_facets.cpp b/src/numeric/numeric_register_facets.cpp index 20e2093d..9cc6e1f9 100644 --- a/src/numeric/numeric_register_facets.cpp +++ b/src/numeric/numeric_register_facets.cpp @@ -38,25 +38,29 @@ namespace xo { (&FloatOps::multiply, &FloatOps::divide, &FloatOps::add, - &FloatOps::subtract); + &FloatOps::subtract, + &FloatOps::cmp_equal); NumericDispatch::instance().register_impl (&FloatIntegerOps::multiply, &FloatIntegerOps::divide, &FloatIntegerOps::add, - &FloatIntegerOps::subtract); + &FloatIntegerOps::subtract, + &FloatIntegerOps::cmp_equal); NumericDispatch::instance().register_impl (&IntegerFloatOps::multiply, &IntegerFloatOps::divide, &IntegerFloatOps::add, - &IntegerFloatOps::subtract); + &IntegerFloatOps::subtract, + &IntegerFloatOps::cmp_equal); NumericDispatch::instance().register_impl (&IntegerOps::multiply, &IntegerOps::divide, &IntegerOps::add, - &IntegerOps::subtract); + &IntegerOps::subtract, + &IntegerOps::cmp_equal); log && log(xtag("ANumeric.tseq", typeseq::id())); From 77c5f625ffedbf945da2d86c67ba47c71e1b2f77 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 19 Feb 2026 11:56:06 -0800 Subject: [PATCH 06/32] xo-interpreter2 stack: support op!= + trial numeric refactor --- include/xo/numeric/FloatIntegerOps.hpp | 4 ++ include/xo/numeric/FloatOps.hpp | 2 + include/xo/numeric/IntegerOps.hpp | 2 + include/xo/numeric/NumericDispatch.hpp | 22 ++++++- include/xo/numeric/NumericOps.hpp | 13 ++-- include/xo/numeric/NumericPrimitives.hpp | 2 + src/numeric/FloatIntegerOps.cpp | 20 +++++- src/numeric/FloatOps.cpp | 7 +++ src/numeric/IntegerOps.cpp | 7 +++ src/numeric/NumericDispatch.cpp | 80 +++++++++++++++++++++++- src/numeric/NumericPrimitives.cpp | 4 ++ src/numeric/numeric_register_facets.cpp | 12 ++-- 12 files changed, 161 insertions(+), 14 deletions(-) diff --git a/include/xo/numeric/FloatIntegerOps.hpp b/include/xo/numeric/FloatIntegerOps.hpp index 5cf301ad..0ee99710 100644 --- a/include/xo/numeric/FloatIntegerOps.hpp +++ b/include/xo/numeric/FloatIntegerOps.hpp @@ -30,6 +30,8 @@ namespace xo { static obj cmp_equal(obj rcx, DFloat * x, DInteger * y); + static obj cmp_notequal(obj rcx, + DFloat * x, DInteger * y); }; class IntegerFloatOps { @@ -48,6 +50,8 @@ namespace xo { static obj cmp_equal(obj rcx, DInteger * x, DFloat * y); + static obj cmp_notequal(obj rcx, + DInteger * x, DFloat * y); }; } diff --git a/include/xo/numeric/FloatOps.hpp b/include/xo/numeric/FloatOps.hpp index 5f7d06be..88b56442 100644 --- a/include/xo/numeric/FloatOps.hpp +++ b/include/xo/numeric/FloatOps.hpp @@ -29,6 +29,8 @@ namespace xo { static obj cmp_equal(obj rcx, DFloat * x, DFloat * y); + static obj cmp_notequal(obj rcx, + DFloat * x, DFloat * y); }; } diff --git a/include/xo/numeric/IntegerOps.hpp b/include/xo/numeric/IntegerOps.hpp index 001a915f..09306522 100644 --- a/include/xo/numeric/IntegerOps.hpp +++ b/include/xo/numeric/IntegerOps.hpp @@ -31,6 +31,8 @@ namespace xo { static obj cmp_equal(obj rcx, DInteger * x, DInteger * y); + static obj cmp_notequal(obj rcx, + DInteger * x, DInteger * y); }; diff --git a/include/xo/numeric/NumericDispatch.hpp b/include/xo/numeric/NumericDispatch.hpp index 58d06565..c40f8155 100644 --- a/include/xo/numeric/NumericDispatch.hpp +++ b/include/xo/numeric/NumericDispatch.hpp @@ -25,6 +25,7 @@ namespace xo { using typeseq = xo::reflect::typeseq; using KeyType = std::pair; using MappedType = AnonymizedNumericOps; + using BinaryOp = AnonymizedNumericOps::BinaryOp; /** hash function for key_type **/ struct KeyHash { @@ -58,6 +59,16 @@ namespace xo { return s_instance; } + /** multi-dispatch driver. + * Invoke @p member_ptr in AnonymizedNumericOps + **/ + static obj dispatch(obj rcx, + const char * caller, + const char * error_headline, + BinaryOp AnonymizedNumericOps::* member_ptr, + obj x, + obj y); + /** multiply w/ runtime polymorphism (double-dispatch) **/ static obj multiply(obj rcx, @@ -87,6 +98,11 @@ namespace xo { obj x, obj y); + /** compare two numeric values for inequality **/ + static obj cmp_notequal(obj rcx, + obj x, + obj y); + /** report memory use for owned arenas to @p visitor **/ void visit_pools(const MemorySizeVisitor & visitor); @@ -100,7 +116,8 @@ namespace xo { typename NumericOps::BinaryOp_Impl div_fn, typename NumericOps::BinaryOp_Impl add_fn, typename NumericOps::BinaryOp_Impl sub_fn, - typename NumericOps::BinaryOp_Impl cmpeq_fn) { + typename NumericOps::BinaryOp_Impl cmpeq_fn, + typename NumericOps::BinaryOp_Impl cmpne_fn) { KeyType key(typeseq::id().seqno(), typeseq::id().seqno()); @@ -111,7 +128,8 @@ namespace xo { div_fn, add_fn, sub_fn, - cmpeq_fn); + cmpeq_fn, + cmpne_fn); } private: diff --git a/include/xo/numeric/NumericOps.hpp b/include/xo/numeric/NumericOps.hpp index f85b20f4..6d888434 100644 --- a/include/xo/numeric/NumericOps.hpp +++ b/include/xo/numeric/NumericOps.hpp @@ -26,9 +26,10 @@ namespace xo { BinaryOp divide, BinaryOp add, BinaryOp subtract, - BinaryOp cmpeq) + BinaryOp cmpeq, + BinaryOp cmpne) : multiply_{multiply}, divide_{divide}, add_{add}, subtract_{subtract}, - cmpeq_{cmpeq} {} + cmpeq_{cmpeq}, cmpne_{cmpne} {} BinaryOp multiply_ = nullptr; BinaryOp divide_ = nullptr; @@ -37,6 +38,8 @@ namespace xo { /** compare numerics for equality **/ BinaryOp cmpeq_ = nullptr; + /** compare numerics for inequality **/ + BinaryOp cmpne_ = nullptr; }; template @@ -52,12 +55,14 @@ namespace xo { BinaryOp_Impl divide, BinaryOp_Impl add, BinaryOp_Impl subtract, - BinaryOp_Impl cmpeq) { + BinaryOp_Impl cmpeq, + BinaryOp_Impl cmpne) { return AnonymizedNumericOps(reinterpret_cast(multiply), reinterpret_cast(divide), reinterpret_cast(add), reinterpret_cast(subtract), - reinterpret_cast(cmpeq)); + reinterpret_cast(cmpeq), + reinterpret_cast(cmpne)); } }; diff --git a/include/xo/numeric/NumericPrimitives.hpp b/include/xo/numeric/NumericPrimitives.hpp index 8f9c40db..a2cc3cdb 100644 --- a/include/xo/numeric/NumericPrimitives.hpp +++ b/include/xo/numeric/NumericPrimitives.hpp @@ -25,6 +25,8 @@ namespace xo { /** polymorphic (in both arguments) compare (==) **/ static DPrimitive_gco_2_gco_gco s_cmpeq_gco_gco_pm; + /** polymorphic (in both arguments) compare (!=) **/ + static DPrimitive_gco_2_gco_gco s_cmpne_gco_gco_pm; }; } } diff --git a/src/numeric/FloatIntegerOps.cpp b/src/numeric/FloatIntegerOps.cpp index 476a6745..f82e10dc 100644 --- a/src/numeric/FloatIntegerOps.cpp +++ b/src/numeric/FloatIntegerOps.cpp @@ -50,6 +50,14 @@ namespace xo { x->value() == DFloat::value_type(y->value())); } + obj + FloatIntegerOps::cmp_notequal(obj rcx, + DFloat * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), + x->value() != DFloat::value_type(y->value())); + } + // ----- Integer op Float ----- obj @@ -84,8 +92,16 @@ namespace xo { IntegerFloatOps::cmp_equal(obj rcx, DInteger * x, DFloat * y) { - return DFloat::box(rcx.allocator(), - DFloat::value_type(x->value() == y->value())); + return DBoolean::box(rcx.allocator(), + DFloat::value_type(x->value()) == y->value()); + } + + obj + IntegerFloatOps::cmp_notequal(obj rcx, + DInteger * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), + DFloat::value_type(x->value()) != y->value()); } } diff --git a/src/numeric/FloatOps.cpp b/src/numeric/FloatOps.cpp index d0aa57aa..6f984728 100644 --- a/src/numeric/FloatOps.cpp +++ b/src/numeric/FloatOps.cpp @@ -47,6 +47,13 @@ namespace xo { return DBoolean::box(rcx.allocator(), x->value() == y->value()); } + obj + FloatOps::cmp_notequal(obj rcx, + DFloat * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), x->value() != y->value()); + } + } } diff --git a/src/numeric/IntegerOps.cpp b/src/numeric/IntegerOps.cpp index 062cbeef..31f9110d 100644 --- a/src/numeric/IntegerOps.cpp +++ b/src/numeric/IntegerOps.cpp @@ -48,6 +48,13 @@ namespace xo { return DBoolean::box(rcx.allocator(), x->value() == y->value()); } + obj + IntegerOps::cmp_notequal(obj rcx, + DInteger * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), x->value() != y->value()); + } + } } diff --git a/src/numeric/NumericDispatch.cpp b/src/numeric/NumericDispatch.cpp index 935d92eb..a40c0efc 100644 --- a/src/numeric/NumericDispatch.cpp +++ b/src/numeric/NumericDispatch.cpp @@ -4,10 +4,13 @@ **/ #include "NumericDispatch.hpp" +#include +#include #include namespace xo { using xo::mm::AGCObject; + using xo::facet::TypeRegistry; namespace scm { @@ -17,6 +20,35 @@ namespace xo { dispatch_.visit_pools(visitor); } + obj + NumericDispatch::dispatch(obj rcx, + const char * caller, + const char * error_headline, + BinaryOp AnonymizedNumericOps::* member_ptr, + obj x, + obj y) + { + KeyType key(x._typeseq(), y._typeseq()); + + auto target_fn + = NumericDispatch::instance().dispatch_[key].*member_ptr; + + if (!target_fn) { + // FIXME: use {fmt} here + std::stringstream ss; + tosn(ss, + error_headline, + xtag("x.type", TypeRegistry::id2name(x._typeseq())), + xtag("y.type", TypeRegistry::id2name(y._typeseq()))); + + return DRuntimeError::make(rcx.allocator(), + caller, + ss.str().c_str()); + } + + return (*target_fn)(rcx, x.data(), y.data()); + } + obj NumericDispatch::multiply(obj rcx, obj x, @@ -91,12 +123,56 @@ namespace xo { auto target_fn = NumericDispatch::instance().dispatch_[key].cmpeq_; - if (!target_fn) - assert(false); + if (!target_fn) { + // FIXME: use {fmt} here + std::stringstream ss; + tosn(ss, + "incomparable types in x==y", + xtag("x.type", TypeRegistry::id2name(x._typeseq())), + xtag("y.type", TypeRegistry::id2name(y._typeseq()))); + + return DRuntimeError::make(rcx.allocator(), + "NumericDispatch::cmp_equal", + ss.str().c_str()); + } return (*target_fn)(rcx, x.data(), y.data()); } + obj + NumericDispatch::cmp_notequal(obj rcx, + obj x, + obj y) + { + return dispatch(rcx, + "NumericDispatch::cmp_notequal", + "incomparable types in x!=y", + &AnonymizedNumericOps::cmpne_, + x, y); + +#ifdef OBSOLETE + KeyType key(x._typeseq(), y._typeseq()); + + auto target_fn + = NumericDispatch::instance().dispatch_[key].cmpne_; + + if (!target_fn) { + // FIXME: use {fmt} here + std::stringstream ss; + tosn(ss, + "incomparable types in x==y", + xtag("x.type", TypeRegistry::id2name(x._typeseq())), + xtag("y.type", TypeRegistry::id2name(y._typeseq()))); + + return DRuntimeError::make(rcx.allocator(), + "NumericDispatch::cmp_notequal", + ss.str().c_str()); + } + + return (*target_fn)(rcx, x.data(), y.data()); +#endif + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/numeric/NumericPrimitives.cpp b/src/numeric/NumericPrimitives.cpp index 28031fac..eb8ebf83 100644 --- a/src/numeric/NumericPrimitives.cpp +++ b/src/numeric/NumericPrimitives.cpp @@ -31,6 +31,10 @@ namespace xo { NumericPrimitives::s_cmpeq_gco_gco_pm("_cmpeq", &NumericDispatch::cmp_equal); + DPrimitive_gco_2_gco_gco + NumericPrimitives::s_cmpne_gco_gco_pm("_cmpne", + &NumericDispatch::cmp_notequal); + } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/numeric/numeric_register_facets.cpp b/src/numeric/numeric_register_facets.cpp index 9cc6e1f9..2bb29401 100644 --- a/src/numeric/numeric_register_facets.cpp +++ b/src/numeric/numeric_register_facets.cpp @@ -39,28 +39,32 @@ namespace xo { &FloatOps::divide, &FloatOps::add, &FloatOps::subtract, - &FloatOps::cmp_equal); + &FloatOps::cmp_equal, + &FloatOps::cmp_notequal); NumericDispatch::instance().register_impl (&FloatIntegerOps::multiply, &FloatIntegerOps::divide, &FloatIntegerOps::add, &FloatIntegerOps::subtract, - &FloatIntegerOps::cmp_equal); + &FloatIntegerOps::cmp_equal, + &FloatIntegerOps::cmp_notequal); NumericDispatch::instance().register_impl (&IntegerFloatOps::multiply, &IntegerFloatOps::divide, &IntegerFloatOps::add, &IntegerFloatOps::subtract, - &IntegerFloatOps::cmp_equal); + &IntegerFloatOps::cmp_equal, + &IntegerFloatOps::cmp_notequal); NumericDispatch::instance().register_impl (&IntegerOps::multiply, &IntegerOps::divide, &IntegerOps::add, &IntegerOps::subtract, - &IntegerOps::cmp_equal); + &IntegerOps::cmp_equal, + &IntegerOps::cmp_notequal); log && log(xtag("ANumeric.tseq", typeseq::id())); From fdad9231837dc2944169ae97ac24a67218650047 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 23 Feb 2026 07:04:13 +1100 Subject: [PATCH 07/32] xo-numeric: streamline using Numeirc::dispatch aux fn --- src/numeric/NumericDispatch.cpp | 62 +++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/src/numeric/NumericDispatch.cpp b/src/numeric/NumericDispatch.cpp index a40c0efc..b0738342 100644 --- a/src/numeric/NumericDispatch.cpp +++ b/src/numeric/NumericDispatch.cpp @@ -54,6 +54,13 @@ namespace xo { obj x, obj y) { + return dispatch(rcx, + "NumericDispatch::multiply", + "incomparable types in x*y", + &AnonymizedNumericOps::multiply_, + x, y); + +#ifdef OBSOLETE KeyType key(x._typeseq(), y._typeseq()); auto target_fn @@ -63,6 +70,7 @@ namespace xo { assert(false); return (*target_fn)(rcx, x.data(), y.data()); +#endif } obj @@ -70,6 +78,13 @@ namespace xo { obj x, obj y) { + return dispatch(rcx, + "NumericDispatch::divide", + "incomparable types in x/y", + &AnonymizedNumericOps::divide_, + x, y); + +#ifdef OBSOLETE KeyType key(x._typeseq(), y._typeseq()); auto target_fn @@ -79,6 +94,7 @@ namespace xo { assert(false); return (*target_fn)(rcx, x.data(), y.data()); +#endif } obj @@ -86,6 +102,13 @@ namespace xo { obj x, obj y) { + return dispatch(rcx, + "NumericDispatch::add", + "incomparable types in x+y", + &AnonymizedNumericOps::add_, + x, y); + +#ifdef OBSOLETE KeyType key(x._typeseq(), y._typeseq()); auto target_fn @@ -95,6 +118,7 @@ namespace xo { assert(false); return (*target_fn)(rcx, x.data(), y.data()); +#endif } obj @@ -102,6 +126,13 @@ namespace xo { obj x, obj y) { + return dispatch(rcx, + "NumericDispatch::subtract", + "incomparable types in x-y", + &AnonymizedNumericOps::subtract_, + x, y); + +#ifdef OBSOLETE KeyType key(x._typeseq(), y._typeseq()); auto target_fn @@ -111,6 +142,7 @@ namespace xo { assert(false); return (*target_fn)(rcx, x.data(), y.data()); +#endif } obj @@ -118,6 +150,13 @@ namespace xo { obj x, obj y) { + return dispatch(rcx, + "NumericDispatch::cmp_equal", + "incomparable types in x==y", + &AnonymizedNumericOps::cmpeq_, + x, y); + +#ifdef OBSOLETE KeyType key(x._typeseq(), y._typeseq()); auto target_fn @@ -137,6 +176,7 @@ namespace xo { } return (*target_fn)(rcx, x.data(), y.data()); +#endif } obj @@ -149,28 +189,6 @@ namespace xo { "incomparable types in x!=y", &AnonymizedNumericOps::cmpne_, x, y); - -#ifdef OBSOLETE - KeyType key(x._typeseq(), y._typeseq()); - - auto target_fn - = NumericDispatch::instance().dispatch_[key].cmpne_; - - if (!target_fn) { - // FIXME: use {fmt} here - std::stringstream ss; - tosn(ss, - "incomparable types in x==y", - xtag("x.type", TypeRegistry::id2name(x._typeseq())), - xtag("y.type", TypeRegistry::id2name(y._typeseq()))); - - return DRuntimeError::make(rcx.allocator(), - "NumericDispatch::cmp_notequal", - ss.str().c_str()); - } - - return (*target_fn)(rcx, x.data(), y.data()); -#endif } } /*namespace scm*/ From 5791cd59ced7d8723348da382dce9dea31b371a7 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 27 Feb 2026 22:55:14 +1100 Subject: [PATCH 08/32] xo-numeric: + less than dispatch (also in schematika parser) --- include/xo/numeric/FloatIntegerOps.hpp | 4 ++++ include/xo/numeric/FloatOps.hpp | 2 ++ include/xo/numeric/IntegerOps.hpp | 2 ++ include/xo/numeric/NumericDispatch.hpp | 11 +++++++++-- include/xo/numeric/NumericOps.hpp | 17 +++++++++++------ include/xo/numeric/NumericPrimitives.hpp | 2 ++ src/numeric/FloatIntegerOps.cpp | 16 ++++++++++++++++ src/numeric/FloatOps.cpp | 7 ++++++- src/numeric/IntegerOps.cpp | 7 +++++++ src/numeric/NumericDispatch.cpp | 12 ++++++++++++ src/numeric/NumericPrimitives.cpp | 4 ++++ src/numeric/numeric_register_facets.cpp | 12 ++++++++---- 12 files changed, 83 insertions(+), 13 deletions(-) diff --git a/include/xo/numeric/FloatIntegerOps.hpp b/include/xo/numeric/FloatIntegerOps.hpp index 0ee99710..35827e6c 100644 --- a/include/xo/numeric/FloatIntegerOps.hpp +++ b/include/xo/numeric/FloatIntegerOps.hpp @@ -32,6 +32,8 @@ namespace xo { DFloat * x, DInteger * y); static obj cmp_notequal(obj rcx, DFloat * x, DInteger * y); + static obj cmp_less(obj rcx, + DFloat * x, DInteger * y); }; class IntegerFloatOps { @@ -52,6 +54,8 @@ namespace xo { DInteger * x, DFloat * y); static obj cmp_notequal(obj rcx, DInteger * x, DFloat * y); + static obj cmp_less(obj rcx, + DInteger * x, DFloat * y); }; } diff --git a/include/xo/numeric/FloatOps.hpp b/include/xo/numeric/FloatOps.hpp index 88b56442..dd088f90 100644 --- a/include/xo/numeric/FloatOps.hpp +++ b/include/xo/numeric/FloatOps.hpp @@ -31,6 +31,8 @@ namespace xo { DFloat * x, DFloat * y); static obj cmp_notequal(obj rcx, DFloat * x, DFloat * y); + static obj cmp_less(obj rcx, + DFloat * x, DFloat * y); }; } diff --git a/include/xo/numeric/IntegerOps.hpp b/include/xo/numeric/IntegerOps.hpp index 09306522..b5a8fba8 100644 --- a/include/xo/numeric/IntegerOps.hpp +++ b/include/xo/numeric/IntegerOps.hpp @@ -33,6 +33,8 @@ namespace xo { DInteger * x, DInteger * y); static obj cmp_notequal(obj rcx, DInteger * x, DInteger * y); + static obj cmp_less(obj rcx, + DInteger * x, DInteger * y); }; diff --git a/include/xo/numeric/NumericDispatch.hpp b/include/xo/numeric/NumericDispatch.hpp index c40f8155..9de42160 100644 --- a/include/xo/numeric/NumericDispatch.hpp +++ b/include/xo/numeric/NumericDispatch.hpp @@ -103,6 +103,11 @@ namespace xo { obj x, obj y); + /** compare two numeric values for inequality **/ + static obj cmp_less(obj rcx, + obj x, + obj y); + /** report memory use for owned arenas to @p visitor **/ void visit_pools(const MemorySizeVisitor & visitor); @@ -117,7 +122,8 @@ namespace xo { typename NumericOps::BinaryOp_Impl add_fn, typename NumericOps::BinaryOp_Impl sub_fn, typename NumericOps::BinaryOp_Impl cmpeq_fn, - typename NumericOps::BinaryOp_Impl cmpne_fn) { + typename NumericOps::BinaryOp_Impl cmpne_fn, + typename NumericOps::BinaryOp_Impl cmplt_fn) { KeyType key(typeseq::id().seqno(), typeseq::id().seqno()); @@ -129,7 +135,8 @@ namespace xo { add_fn, sub_fn, cmpeq_fn, - cmpne_fn); + cmpne_fn, + cmplt_fn); } private: diff --git a/include/xo/numeric/NumericOps.hpp b/include/xo/numeric/NumericOps.hpp index 6d888434..b69a0338 100644 --- a/include/xo/numeric/NumericOps.hpp +++ b/include/xo/numeric/NumericOps.hpp @@ -27,19 +27,22 @@ namespace xo { BinaryOp add, BinaryOp subtract, BinaryOp cmpeq, - BinaryOp cmpne) + BinaryOp cmpne, + BinaryOp cmplt) : multiply_{multiply}, divide_{divide}, add_{add}, subtract_{subtract}, - cmpeq_{cmpeq}, cmpne_{cmpne} {} + cmpeq_{cmpeq}, cmpne_{cmpne}, cmplt_{cmplt} {} BinaryOp multiply_ = nullptr; BinaryOp divide_ = nullptr; BinaryOp add_ = nullptr; BinaryOp subtract_ = nullptr; - /** compare numerics for equality **/ + /** compare numerics (==) **/ BinaryOp cmpeq_ = nullptr; - /** compare numerics for inequality **/ + /** compare numerics (!=) **/ BinaryOp cmpne_ = nullptr; + /** compare numerics (<) **/ + BinaryOp cmplt_ = nullptr; }; template @@ -56,13 +59,15 @@ namespace xo { BinaryOp_Impl add, BinaryOp_Impl subtract, BinaryOp_Impl cmpeq, - BinaryOp_Impl cmpne) { + BinaryOp_Impl cmpne, + BinaryOp_Impl cmplt) { return AnonymizedNumericOps(reinterpret_cast(multiply), reinterpret_cast(divide), reinterpret_cast(add), reinterpret_cast(subtract), reinterpret_cast(cmpeq), - reinterpret_cast(cmpne)); + reinterpret_cast(cmpne), + reinterpret_cast(cmplt)); } }; diff --git a/include/xo/numeric/NumericPrimitives.hpp b/include/xo/numeric/NumericPrimitives.hpp index a2cc3cdb..b67ec911 100644 --- a/include/xo/numeric/NumericPrimitives.hpp +++ b/include/xo/numeric/NumericPrimitives.hpp @@ -27,6 +27,8 @@ namespace xo { static DPrimitive_gco_2_gco_gco s_cmpeq_gco_gco_pm; /** polymorphic (in both arguments) compare (!=) **/ static DPrimitive_gco_2_gco_gco s_cmpne_gco_gco_pm; + /** polymorphic (in both arguments) compare (<) **/ + static DPrimitive_gco_2_gco_gco s_cmplt_gco_gco_pm; }; } } diff --git a/src/numeric/FloatIntegerOps.cpp b/src/numeric/FloatIntegerOps.cpp index f82e10dc..c601a2bf 100644 --- a/src/numeric/FloatIntegerOps.cpp +++ b/src/numeric/FloatIntegerOps.cpp @@ -58,6 +58,14 @@ namespace xo { x->value() != DFloat::value_type(y->value())); } + obj + FloatIntegerOps::cmp_less(obj rcx, + DFloat * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), + x->value() < DFloat::value_type(y->value())); + } + // ----- Integer op Float ----- obj @@ -104,6 +112,14 @@ namespace xo { DFloat::value_type(x->value()) != y->value()); } + obj + IntegerFloatOps::cmp_less(obj rcx, + DInteger * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), + DFloat::value_type(x->value()) < y->value()); + } + } } diff --git a/src/numeric/FloatOps.cpp b/src/numeric/FloatOps.cpp index 6f984728..8fbefc59 100644 --- a/src/numeric/FloatOps.cpp +++ b/src/numeric/FloatOps.cpp @@ -54,7 +54,12 @@ namespace xo { return DBoolean::box(rcx.allocator(), x->value() != y->value()); } - + obj + FloatOps::cmp_less(obj rcx, + DFloat * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), x->value() < y->value()); + } } } diff --git a/src/numeric/IntegerOps.cpp b/src/numeric/IntegerOps.cpp index 31f9110d..52c9596c 100644 --- a/src/numeric/IntegerOps.cpp +++ b/src/numeric/IntegerOps.cpp @@ -55,6 +55,13 @@ namespace xo { return DBoolean::box(rcx.allocator(), x->value() != y->value()); } + obj + IntegerOps::cmp_less(obj rcx, + DInteger * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), x->value() < y->value()); + } + } } diff --git a/src/numeric/NumericDispatch.cpp b/src/numeric/NumericDispatch.cpp index b0738342..9220207e 100644 --- a/src/numeric/NumericDispatch.cpp +++ b/src/numeric/NumericDispatch.cpp @@ -191,6 +191,18 @@ namespace xo { x, y); } + obj + NumericDispatch::cmp_less(obj rcx, + obj x, + obj y) + { + return dispatch(rcx, + "NumericDispatch::cmp_less", + "incomparable types in x (&FloatIntegerOps::multiply, @@ -48,7 +49,8 @@ namespace xo { &FloatIntegerOps::add, &FloatIntegerOps::subtract, &FloatIntegerOps::cmp_equal, - &FloatIntegerOps::cmp_notequal); + &FloatIntegerOps::cmp_notequal, + &FloatIntegerOps::cmp_less); NumericDispatch::instance().register_impl (&IntegerFloatOps::multiply, @@ -56,7 +58,8 @@ namespace xo { &IntegerFloatOps::add, &IntegerFloatOps::subtract, &IntegerFloatOps::cmp_equal, - &IntegerFloatOps::cmp_notequal); + &IntegerFloatOps::cmp_notequal, + &IntegerFloatOps::cmp_less); NumericDispatch::instance().register_impl (&IntegerOps::multiply, @@ -64,7 +67,8 @@ namespace xo { &IntegerOps::add, &IntegerOps::subtract, &IntegerOps::cmp_equal, - &IntegerOps::cmp_notequal); + &IntegerOps::cmp_notequal, + &IntegerOps::cmp_less); log && log(xtag("ANumeric.tseq", typeseq::id())); From 0083f23aae1c2b684437825e7b083962b1bec5ef Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 4 Mar 2026 14:05:10 +1100 Subject: [PATCH 09/32] xo-numeric: expand error message on bad dispatch --- src/numeric/NumericDispatch.cpp | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/numeric/NumericDispatch.cpp b/src/numeric/NumericDispatch.cpp index 9220207e..85936171 100644 --- a/src/numeric/NumericDispatch.cpp +++ b/src/numeric/NumericDispatch.cpp @@ -38,8 +38,12 @@ namespace xo { std::stringstream ss; tosn(ss, error_headline, + xtag("x.tseq", x._typeseq()), xtag("x.type", TypeRegistry::id2name(x._typeseq())), - xtag("y.type", TypeRegistry::id2name(y._typeseq()))); + xtag("x.data", x.data()), + xtag("y.tseq", y._typeseq()), + xtag("y.type", TypeRegistry::id2name(y._typeseq())), + xtag("y.data", y.data())); return DRuntimeError::make(rcx.allocator(), caller, @@ -59,18 +63,6 @@ namespace xo { "incomparable types in x*y", &AnonymizedNumericOps::multiply_, x, y); - -#ifdef OBSOLETE - KeyType key(x._typeseq(), y._typeseq()); - - auto target_fn - = NumericDispatch::instance().dispatch_[key].multiply_; - - if (!target_fn) - assert(false); - - return (*target_fn)(rcx, x.data(), y.data()); -#endif } obj From 94c98c8396f26099ce312f9bd2e74d8ca7cac5d6 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 4 Mar 2026 22:26:31 +1100 Subject: [PATCH 10/32] xo-gc xo-alloc2: move Collector faceet gc/ -> alloc2/ for levelling --- include/xo/numeric/NumericDispatch.hpp | 2 +- include/xo/numeric/NumericOps.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/xo/numeric/NumericDispatch.hpp b/include/xo/numeric/NumericDispatch.hpp index 9de42160..1dc68a3d 100644 --- a/include/xo/numeric/NumericDispatch.hpp +++ b/include/xo/numeric/NumericDispatch.hpp @@ -7,7 +7,7 @@ #include "NumericOps.hpp" #include -#include +#include #include #include diff --git a/include/xo/numeric/NumericOps.hpp b/include/xo/numeric/NumericOps.hpp index b69a0338..580efcf1 100644 --- a/include/xo/numeric/NumericOps.hpp +++ b/include/xo/numeric/NumericOps.hpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include namespace xo { From d1cba49323931a746900ce8b1c00cf2d025c0e3a Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 11 Mar 2026 08:41:57 -0500 Subject: [PATCH 11/32] build: retiring REPR argument to xo_add_genfacetimpl() --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 92d4b9e7..b63fe4a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,7 @@ xo_add_genfacetimpl( TARGET xo-numeric-facetimpl-numeric-float FACET_PKG xo_numeric FACET Numeric - REPR Float +# REPR Float INPUT idl/INumeric_DFloat.json5 ) @@ -43,7 +43,7 @@ xo_add_genfacetimpl( TARGET xo-numeric-facetimpl-numeric-integer FACET_PKG xo_numeric FACET Numeric - REPR Integer +# REPR Integer INPUT idl/INumeric_DInteger.json5 ) From 6f76c9ee3bd3bd5a678c44da8b3f7117dea1bef4 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 11 Mar 2026 10:03:46 -0500 Subject: [PATCH 12/32] build: retire FACET argument to genfacetimpl --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b63fe4a0..fa98c6a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,6 @@ xo_add_genfacet( xo_add_genfacetimpl( TARGET xo-numeric-facetimpl-numeric-float FACET_PKG xo_numeric - FACET Numeric # REPR Float INPUT idl/INumeric_DFloat.json5 ) @@ -42,7 +41,6 @@ xo_add_genfacetimpl( xo_add_genfacetimpl( TARGET xo-numeric-facetimpl-numeric-integer FACET_PKG xo_numeric - FACET Numeric # REPR Integer INPUT idl/INumeric_DInteger.json5 ) From b69ec48d00e82decc5f749291e7890efc85f08a6 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 12 Mar 2026 20:26:08 -0500 Subject: [PATCH 13/32] xo-interpreter2 stack: refactor + bugfix operator expr --- include/xo/numeric/NumericPrimitives.hpp | 20 +++-- .../numeric/numeric_register_primitives.hpp | 20 +++++ src/numeric/CMakeLists.txt | 1 + src/numeric/NumericPrimitives.cpp | 67 +++++++++------ src/numeric/init_numeric.cpp | 6 ++ src/numeric/numeric_register_primitives.cpp | 81 +++++++++++++++++++ 6 files changed, 164 insertions(+), 31 deletions(-) create mode 100644 include/xo/numeric/numeric_register_primitives.hpp create mode 100644 src/numeric/numeric_register_primitives.cpp diff --git a/include/xo/numeric/NumericPrimitives.hpp b/include/xo/numeric/NumericPrimitives.hpp index b67ec911..feacb480 100644 --- a/include/xo/numeric/NumericPrimitives.hpp +++ b/include/xo/numeric/NumericPrimitives.hpp @@ -14,21 +14,25 @@ namespace xo { **/ class NumericPrimitives { public: - /** polymorphic (in both arguments) multiply **/ - static DPrimitive_gco_2_gco_gco s_mul_gco_gco_pm; + using AAllocator = xo::mm::AAllocator; + + public: + /** polymorphic (in both arguments1) multiply **/ + static DPrimitive_gco_2_gco_gco * make_multiply_pm(obj mm); + /** polymorphic (in both arguments) divide **/ - static DPrimitive_gco_2_gco_gco s_div_gco_gco_pm; + static DPrimitive_gco_2_gco_gco * make_divide_pm(obj mm); /** polymorphic (in both arguments) add **/ - static DPrimitive_gco_2_gco_gco s_add_gco_gco_pm; + static DPrimitive_gco_2_gco_gco * make_add_pm(obj mm); /** polymorphic (in both arguments) subtract **/ - static DPrimitive_gco_2_gco_gco s_sub_gco_gco_pm; + static DPrimitive_gco_2_gco_gco * make_subtract_pm(obj mm); /** polymorphic (in both arguments) compare (==) **/ - static DPrimitive_gco_2_gco_gco s_cmpeq_gco_gco_pm; + static DPrimitive_gco_2_gco_gco * make_cmpeq_pm(obj mm); /** polymorphic (in both arguments) compare (!=) **/ - static DPrimitive_gco_2_gco_gco s_cmpne_gco_gco_pm; + static DPrimitive_gco_2_gco_gco * make_cmpne_pm(obj mm); /** polymorphic (in both arguments) compare (<) **/ - static DPrimitive_gco_2_gco_gco s_cmplt_gco_gco_pm; + static DPrimitive_gco_2_gco_gco * make_cmplt_pm(obj mm); }; } } diff --git a/include/xo/numeric/numeric_register_primitives.hpp b/include/xo/numeric/numeric_register_primitives.hpp new file mode 100644 index 00000000..455d8b44 --- /dev/null +++ b/include/xo/numeric/numeric_register_primitives.hpp @@ -0,0 +1,20 @@ +/** @file numeric_register_primitives.hpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#pragma once + +#include "PrimitiveRegistry.hpp" +#include + +namespace xo { + namespace scm { + /** Register gc-aware (AGCObject,DRepr) combinations with garbage collector @p gc **/ + bool numeric_register_primitives(obj gc, + InstallSink sink, + InstallFlags flags); + } +} + +/* end numeric_register_primitives.hpp */ diff --git a/src/numeric/CMakeLists.txt b/src/numeric/CMakeLists.txt index 4d2b4345..ca7dd6d5 100644 --- a/src/numeric/CMakeLists.txt +++ b/src/numeric/CMakeLists.txt @@ -4,6 +4,7 @@ set(SELF_LIB xo_numeric) set(SELF_SRCS init_numeric.cpp numeric_register_facets.cpp + numeric_register_primitives.cpp NumericPrimitives.cpp NumericDispatch.cpp INumeric_Any.cpp diff --git a/src/numeric/NumericPrimitives.cpp b/src/numeric/NumericPrimitives.cpp index f9cdf4d2..fabc3648 100644 --- a/src/numeric/NumericPrimitives.cpp +++ b/src/numeric/NumericPrimitives.cpp @@ -7,38 +7,59 @@ #include "NumericDispatch.hpp" namespace xo { - using xo::mm::AGCObject; + using xo::mm::AAllocator; + //using xo::mm::AGCObject; namespace scm { - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_mul_gco_gco_pm("_mul", - &NumericDispatch::multiply); + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_multiply_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_mul", + &NumericDispatch::multiply); + } - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_div_gco_gco_pm("_div", - &NumericDispatch::divide); + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_divide_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_div", + &NumericDispatch::divide); + } - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_add_gco_gco_pm("_add", - &NumericDispatch::add); + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_add_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_add", + &NumericDispatch::add); + } - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_sub_gco_gco_pm("_sub", - &NumericDispatch::subtract); + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_subtract_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_sub", + &NumericDispatch::subtract); + } - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_cmpeq_gco_gco_pm("_cmpeq", - &NumericDispatch::cmp_equal); + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmpeq_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpeq", + &NumericDispatch::cmp_equal); + } - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_cmpne_gco_gco_pm("_cmpne", - &NumericDispatch::cmp_notequal); - - DPrimitive_gco_2_gco_gco - NumericPrimitives::s_cmplt_gco_gco_pm("_cmplt", - &NumericDispatch::cmp_less); + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmpne_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpne", + &NumericDispatch::cmp_notequal); + } + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmplt_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmplt", + &NumericDispatch::cmp_less); + } } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/numeric/init_numeric.cpp b/src/numeric/init_numeric.cpp index 1b205585..faa678a0 100644 --- a/src/numeric/init_numeric.cpp +++ b/src/numeric/init_numeric.cpp @@ -7,14 +7,20 @@ #include #include "Subsystem.hpp" #include "numeric_register_facets.hpp" +#include "numeric_register_primitives.hpp" namespace xo { using xo::scm::numeric_register_facets; + using xo::scm::numeric_register_primitives; + using xo::scm::PrimitiveRegistry; void InitSubsys::init() { numeric_register_facets(); + + PrimitiveRegistry::instance().register_primitives(&numeric_register_primitives); + } InitEvidence diff --git a/src/numeric/numeric_register_primitives.cpp b/src/numeric/numeric_register_primitives.cpp new file mode 100644 index 00000000..e407eca8 --- /dev/null +++ b/src/numeric/numeric_register_primitives.cpp @@ -0,0 +1,81 @@ +/** @file numeric_register_primitives.cpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#include "numeric_register_primitives.hpp" +#include "NumericPrimitives.hpp" +#include "NumericDispatch.hpp" +#include +#include + +namespace xo { + using xo::mm::AAllocator; + using xo::scope; + + namespace scm { + namespace { + bool install_aux(InstallSink sink, + DPrimitive_gco_2_gco_gco * pm, + InstallFlags flags) + { + if (flags != InstallFlags::f_none) { + return sink(pm->name(), + pm->fn_td(), + obj(pm), + flags); + } else { + return true; + } + } + + bool install_aux(InstallSink sink, + obj mm, + std::string_view name, + obj (*impl)(obj rcx, + obj x, + obj y), + InstallFlags flags) + { + if (flags != InstallFlags::f_none) { + auto pm + = DPrimitive_gco_2_gco_gco::_make(mm, name, impl); + + return install_aux(sink, pm, flags); + } else { + return true; + } + } + } + + bool + numeric_register_primitives(obj mm, InstallSink sink, InstallFlags flags) + { + scope log(XO_DEBUG(true)); + + bool ok = true; + + ok = ok & install_aux(sink, + NumericPrimitives::make_multiply_pm(mm), + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, + NumericPrimitives::make_divide_pm(mm), + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, mm, "_add", &NumericDispatch::add, + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, mm, "_sub", &NumericDispatch::subtract, + flags & InstallFlags::f_essential); + + ok = ok & install_aux(sink, mm, "_cmpeq", &NumericDispatch::cmp_equal, + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, mm, "_cmpne", &NumericDispatch::cmp_notequal, + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, mm, "_cmplt", &NumericDispatch::cmp_less, + flags & InstallFlags::f_essential); + + return ok; + } + } +} /*namespace xo*/ + +/* end numeric_register_primitives.cpp */ From 1a60284861dc694c12ade24fd7693eef313d7020 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 12 Mar 2026 20:54:23 -0500 Subject: [PATCH 14/32] xo-numeric: + cmple for op<= --- include/xo/numeric/FloatIntegerOps.hpp | 4 ++ include/xo/numeric/FloatOps.hpp | 2 + include/xo/numeric/IntegerOps.hpp | 2 + include/xo/numeric/NumericDispatch.hpp | 13 ++++-- include/xo/numeric/NumericOps.hpp | 13 ++++-- include/xo/numeric/NumericPrimitives.hpp | 2 + src/numeric/FloatIntegerOps.cpp | 16 +++++++ src/numeric/FloatOps.cpp | 7 +++ src/numeric/IntegerOps.cpp | 7 +++ src/numeric/NumericDispatch.cpp | 57 +++++------------------- src/numeric/NumericPrimitives.cpp | 7 +++ src/numeric/numeric_register_facets.cpp | 12 +++-- 12 files changed, 86 insertions(+), 56 deletions(-) diff --git a/include/xo/numeric/FloatIntegerOps.hpp b/include/xo/numeric/FloatIntegerOps.hpp index 35827e6c..da13d7c4 100644 --- a/include/xo/numeric/FloatIntegerOps.hpp +++ b/include/xo/numeric/FloatIntegerOps.hpp @@ -34,6 +34,8 @@ namespace xo { DFloat * x, DInteger * y); static obj cmp_less(obj rcx, DFloat * x, DInteger * y); + static obj cmp_lessequal(obj rcx, + DFloat * x, DInteger * y); }; class IntegerFloatOps { @@ -56,6 +58,8 @@ namespace xo { DInteger * x, DFloat * y); static obj cmp_less(obj rcx, DInteger * x, DFloat * y); + static obj cmp_lessequal(obj rcx, + DInteger * x, DFloat * y); }; } diff --git a/include/xo/numeric/FloatOps.hpp b/include/xo/numeric/FloatOps.hpp index dd088f90..3c32960b 100644 --- a/include/xo/numeric/FloatOps.hpp +++ b/include/xo/numeric/FloatOps.hpp @@ -33,6 +33,8 @@ namespace xo { DFloat * x, DFloat * y); static obj cmp_less(obj rcx, DFloat * x, DFloat * y); + static obj cmp_lessequal(obj rcx, + DFloat * x, DFloat * y); }; } diff --git a/include/xo/numeric/IntegerOps.hpp b/include/xo/numeric/IntegerOps.hpp index b5a8fba8..4612e365 100644 --- a/include/xo/numeric/IntegerOps.hpp +++ b/include/xo/numeric/IntegerOps.hpp @@ -35,6 +35,8 @@ namespace xo { DInteger * x, DInteger * y); static obj cmp_less(obj rcx, DInteger * x, DInteger * y); + static obj cmp_lessequal(obj rcx, + DInteger * x, DInteger * y); }; diff --git a/include/xo/numeric/NumericDispatch.hpp b/include/xo/numeric/NumericDispatch.hpp index 1dc68a3d..3680a508 100644 --- a/include/xo/numeric/NumericDispatch.hpp +++ b/include/xo/numeric/NumericDispatch.hpp @@ -103,11 +103,16 @@ namespace xo { obj x, obj y); - /** compare two numeric values for inequality **/ + /** compare two numeric values for less **/ static obj cmp_less(obj rcx, obj x, obj y); + /** compare two numeric values for less-or-equal **/ + static obj cmp_lessequal(obj rcx, + obj x, + obj y); + /** report memory use for owned arenas to @p visitor **/ void visit_pools(const MemorySizeVisitor & visitor); @@ -123,7 +128,8 @@ namespace xo { typename NumericOps::BinaryOp_Impl sub_fn, typename NumericOps::BinaryOp_Impl cmpeq_fn, typename NumericOps::BinaryOp_Impl cmpne_fn, - typename NumericOps::BinaryOp_Impl cmplt_fn) { + typename NumericOps::BinaryOp_Impl cmplt_fn, + typename NumericOps::BinaryOp_Impl cmple_fn) { KeyType key(typeseq::id().seqno(), typeseq::id().seqno()); @@ -136,7 +142,8 @@ namespace xo { sub_fn, cmpeq_fn, cmpne_fn, - cmplt_fn); + cmplt_fn, + cmple_fn); } private: diff --git a/include/xo/numeric/NumericOps.hpp b/include/xo/numeric/NumericOps.hpp index 580efcf1..d8916133 100644 --- a/include/xo/numeric/NumericOps.hpp +++ b/include/xo/numeric/NumericOps.hpp @@ -28,9 +28,10 @@ namespace xo { BinaryOp subtract, BinaryOp cmpeq, BinaryOp cmpne, - BinaryOp cmplt) + BinaryOp cmplt, + BinaryOp cmple) : multiply_{multiply}, divide_{divide}, add_{add}, subtract_{subtract}, - cmpeq_{cmpeq}, cmpne_{cmpne}, cmplt_{cmplt} {} + cmpeq_{cmpeq}, cmpne_{cmpne}, cmplt_{cmplt}, cmple_{cmple} {} BinaryOp multiply_ = nullptr; BinaryOp divide_ = nullptr; @@ -43,6 +44,8 @@ namespace xo { BinaryOp cmpne_ = nullptr; /** compare numerics (<) **/ BinaryOp cmplt_ = nullptr; + /** compare numerics (<=) **/ + BinaryOp cmple_ = nullptr; }; template @@ -60,14 +63,16 @@ namespace xo { BinaryOp_Impl subtract, BinaryOp_Impl cmpeq, BinaryOp_Impl cmpne, - BinaryOp_Impl cmplt) { + BinaryOp_Impl cmplt, + BinaryOp_Impl cmple) { return AnonymizedNumericOps(reinterpret_cast(multiply), reinterpret_cast(divide), reinterpret_cast(add), reinterpret_cast(subtract), reinterpret_cast(cmpeq), reinterpret_cast(cmpne), - reinterpret_cast(cmplt)); + reinterpret_cast(cmplt), + reinterpret_cast(cmple)); } }; diff --git a/include/xo/numeric/NumericPrimitives.hpp b/include/xo/numeric/NumericPrimitives.hpp index feacb480..a703af4a 100644 --- a/include/xo/numeric/NumericPrimitives.hpp +++ b/include/xo/numeric/NumericPrimitives.hpp @@ -33,6 +33,8 @@ namespace xo { static DPrimitive_gco_2_gco_gco * make_cmpne_pm(obj mm); /** polymorphic (in both arguments) compare (<) **/ static DPrimitive_gco_2_gco_gco * make_cmplt_pm(obj mm); + /** polymorphic (in both arguments) compare (<=) **/ + static DPrimitive_gco_2_gco_gco * make_cmple_pm(obj mm); }; } } diff --git a/src/numeric/FloatIntegerOps.cpp b/src/numeric/FloatIntegerOps.cpp index c601a2bf..c23d70f4 100644 --- a/src/numeric/FloatIntegerOps.cpp +++ b/src/numeric/FloatIntegerOps.cpp @@ -66,6 +66,14 @@ namespace xo { x->value() < DFloat::value_type(y->value())); } + obj + FloatIntegerOps::cmp_lessequal(obj rcx, + DFloat * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), + x->value() <= DFloat::value_type(y->value())); + } + // ----- Integer op Float ----- obj @@ -120,6 +128,14 @@ namespace xo { DFloat::value_type(x->value()) < y->value()); } + obj + IntegerFloatOps::cmp_lessequal(obj rcx, + DInteger * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), + DFloat::value_type(x->value()) <= y->value()); + } + } } diff --git a/src/numeric/FloatOps.cpp b/src/numeric/FloatOps.cpp index 8fbefc59..8c59bb1f 100644 --- a/src/numeric/FloatOps.cpp +++ b/src/numeric/FloatOps.cpp @@ -60,6 +60,13 @@ namespace xo { { return DBoolean::box(rcx.allocator(), x->value() < y->value()); } + + obj + FloatOps::cmp_lessequal(obj rcx, + DFloat * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), x->value() <= y->value()); + } } } diff --git a/src/numeric/IntegerOps.cpp b/src/numeric/IntegerOps.cpp index 52c9596c..65874439 100644 --- a/src/numeric/IntegerOps.cpp +++ b/src/numeric/IntegerOps.cpp @@ -62,6 +62,13 @@ namespace xo { return DBoolean::box(rcx.allocator(), x->value() < y->value()); } + obj + IntegerOps::cmp_lessequal(obj rcx, + DInteger * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), x->value() <= y->value()); + } + } } diff --git a/src/numeric/NumericDispatch.cpp b/src/numeric/NumericDispatch.cpp index 85936171..42c507ee 100644 --- a/src/numeric/NumericDispatch.cpp +++ b/src/numeric/NumericDispatch.cpp @@ -99,18 +99,6 @@ namespace xo { "incomparable types in x+y", &AnonymizedNumericOps::add_, x, y); - -#ifdef OBSOLETE - KeyType key(x._typeseq(), y._typeseq()); - - auto target_fn - = NumericDispatch::instance().dispatch_[key].add_; - - if (!target_fn) - assert(false); - - return (*target_fn)(rcx, x.data(), y.data()); -#endif } obj @@ -123,18 +111,6 @@ namespace xo { "incomparable types in x-y", &AnonymizedNumericOps::subtract_, x, y); - -#ifdef OBSOLETE - KeyType key(x._typeseq(), y._typeseq()); - - auto target_fn - = NumericDispatch::instance().dispatch_[key].subtract_; - - if (!target_fn) - assert(false); - - return (*target_fn)(rcx, x.data(), y.data()); -#endif } obj @@ -148,27 +124,6 @@ namespace xo { &AnonymizedNumericOps::cmpeq_, x, y); -#ifdef OBSOLETE - KeyType key(x._typeseq(), y._typeseq()); - - auto target_fn - = NumericDispatch::instance().dispatch_[key].cmpeq_; - - if (!target_fn) { - // FIXME: use {fmt} here - std::stringstream ss; - tosn(ss, - "incomparable types in x==y", - xtag("x.type", TypeRegistry::id2name(x._typeseq())), - xtag("y.type", TypeRegistry::id2name(y._typeseq()))); - - return DRuntimeError::make(rcx.allocator(), - "NumericDispatch::cmp_equal", - ss.str().c_str()); - } - - return (*target_fn)(rcx, x.data(), y.data()); -#endif } obj @@ -195,6 +150,18 @@ namespace xo { x, y); } + obj + NumericDispatch::cmp_lessequal(obj rcx, + obj x, + obj y) + { + return dispatch(rcx, + "NumericDispatch::cmp_lessequal", + "incomparable types in x<=y", + &AnonymizedNumericOps::cmple_, + x, y); + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/numeric/NumericPrimitives.cpp b/src/numeric/NumericPrimitives.cpp index fabc3648..e48c1a30 100644 --- a/src/numeric/NumericPrimitives.cpp +++ b/src/numeric/NumericPrimitives.cpp @@ -61,6 +61,13 @@ namespace xo { &NumericDispatch::cmp_less); } + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmple_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmple", + &NumericDispatch::cmp_lessequal); + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/numeric/numeric_register_facets.cpp b/src/numeric/numeric_register_facets.cpp index 1d7a6a13..fce3dc27 100644 --- a/src/numeric/numeric_register_facets.cpp +++ b/src/numeric/numeric_register_facets.cpp @@ -41,7 +41,8 @@ namespace xo { &FloatOps::subtract, &FloatOps::cmp_equal, &FloatOps::cmp_notequal, - &FloatOps::cmp_less); + &FloatOps::cmp_less, + &FloatOps::cmp_lessequal); NumericDispatch::instance().register_impl (&FloatIntegerOps::multiply, @@ -50,7 +51,8 @@ namespace xo { &FloatIntegerOps::subtract, &FloatIntegerOps::cmp_equal, &FloatIntegerOps::cmp_notequal, - &FloatIntegerOps::cmp_less); + &FloatIntegerOps::cmp_less, + &FloatIntegerOps::cmp_lessequal); NumericDispatch::instance().register_impl (&IntegerFloatOps::multiply, @@ -59,7 +61,8 @@ namespace xo { &IntegerFloatOps::subtract, &IntegerFloatOps::cmp_equal, &IntegerFloatOps::cmp_notequal, - &IntegerFloatOps::cmp_less); + &IntegerFloatOps::cmp_less, + &IntegerFloatOps::cmp_lessequal); NumericDispatch::instance().register_impl (&IntegerOps::multiply, @@ -68,7 +71,8 @@ namespace xo { &IntegerOps::subtract, &IntegerOps::cmp_equal, &IntegerOps::cmp_notequal, - &IntegerOps::cmp_less); + &IntegerOps::cmp_less, + &IntegerOps::cmp_lessequal); log && log(xtag("ANumeric.tseq", typeseq::id())); From 380449a72aeef246c5d4a81e92866f7e6c4e0650 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 12 Mar 2026 21:00:16 -0500 Subject: [PATCH 15/32] xo-reader2 stack: + op<= setup --- src/numeric/numeric_register_primitives.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/numeric/numeric_register_primitives.cpp b/src/numeric/numeric_register_primitives.cpp index e407eca8..ed5d777f 100644 --- a/src/numeric/numeric_register_primitives.cpp +++ b/src/numeric/numeric_register_primitives.cpp @@ -72,6 +72,8 @@ namespace xo { flags & InstallFlags::f_essential); ok = ok & install_aux(sink, mm, "_cmplt", &NumericDispatch::cmp_less, flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, mm, "_cmple", &NumericDispatch::cmp_lessequal, + flags & InstallFlags::f_essential); return ok; } From 1b4d5744d25670c38f5c07b5975647b20771402f Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 12 Mar 2026 23:41:21 -0500 Subject: [PATCH 16/32] xo-reader2: + op>= support --- include/xo/numeric/FloatIntegerOps.hpp | 4 +++ include/xo/numeric/FloatOps.hpp | 2 ++ include/xo/numeric/IntegerOps.hpp | 2 ++ include/xo/numeric/NumericDispatch.hpp | 11 ++++++-- include/xo/numeric/NumericOps.hpp | 13 ++++++--- src/numeric/FloatIntegerOps.cpp | 16 ++++++++++++ src/numeric/FloatOps.cpp | 29 ++++++++++++++++----- src/numeric/IntegerOps.cpp | 7 +++++ src/numeric/NumericDispatch.cpp | 12 +++++++++ src/numeric/numeric_register_facets.cpp | 12 ++++++--- src/numeric/numeric_register_primitives.cpp | 2 ++ 11 files changed, 93 insertions(+), 17 deletions(-) diff --git a/include/xo/numeric/FloatIntegerOps.hpp b/include/xo/numeric/FloatIntegerOps.hpp index da13d7c4..8508402f 100644 --- a/include/xo/numeric/FloatIntegerOps.hpp +++ b/include/xo/numeric/FloatIntegerOps.hpp @@ -36,6 +36,8 @@ namespace xo { DFloat * x, DInteger * y); static obj cmp_lessequal(obj rcx, DFloat * x, DInteger * y); + static obj cmp_greatequal(obj rcx, + DFloat * x, DInteger * y); }; class IntegerFloatOps { @@ -60,6 +62,8 @@ namespace xo { DInteger * x, DFloat * y); static obj cmp_lessequal(obj rcx, DInteger * x, DFloat * y); + static obj cmp_greatequal(obj rcx, + DInteger * x, DFloat * y); }; } diff --git a/include/xo/numeric/FloatOps.hpp b/include/xo/numeric/FloatOps.hpp index 3c32960b..3eaabc9c 100644 --- a/include/xo/numeric/FloatOps.hpp +++ b/include/xo/numeric/FloatOps.hpp @@ -35,6 +35,8 @@ namespace xo { DFloat * x, DFloat * y); static obj cmp_lessequal(obj rcx, DFloat * x, DFloat * y); + static obj cmp_greatequal(obj rcx, + DFloat * x, DFloat * y); }; } diff --git a/include/xo/numeric/IntegerOps.hpp b/include/xo/numeric/IntegerOps.hpp index 4612e365..b8342555 100644 --- a/include/xo/numeric/IntegerOps.hpp +++ b/include/xo/numeric/IntegerOps.hpp @@ -37,6 +37,8 @@ namespace xo { DInteger * x, DInteger * y); static obj cmp_lessequal(obj rcx, DInteger * x, DInteger * y); + static obj cmp_greatequal(obj rcx, + DInteger * x, DInteger * y); }; diff --git a/include/xo/numeric/NumericDispatch.hpp b/include/xo/numeric/NumericDispatch.hpp index 3680a508..53b35b97 100644 --- a/include/xo/numeric/NumericDispatch.hpp +++ b/include/xo/numeric/NumericDispatch.hpp @@ -113,6 +113,11 @@ namespace xo { obj x, obj y); + /** compare two numeric values for greater-or-equal **/ + static obj cmp_greatequal(obj rcx, + obj x, + obj y); + /** report memory use for owned arenas to @p visitor **/ void visit_pools(const MemorySizeVisitor & visitor); @@ -129,7 +134,8 @@ namespace xo { typename NumericOps::BinaryOp_Impl cmpeq_fn, typename NumericOps::BinaryOp_Impl cmpne_fn, typename NumericOps::BinaryOp_Impl cmplt_fn, - typename NumericOps::BinaryOp_Impl cmple_fn) { + typename NumericOps::BinaryOp_Impl cmple_fn, + typename NumericOps::BinaryOp_Impl cmpge_fn) { KeyType key(typeseq::id().seqno(), typeseq::id().seqno()); @@ -143,7 +149,8 @@ namespace xo { cmpeq_fn, cmpne_fn, cmplt_fn, - cmple_fn); + cmple_fn, + cmpge_fn); } private: diff --git a/include/xo/numeric/NumericOps.hpp b/include/xo/numeric/NumericOps.hpp index d8916133..5d983a98 100644 --- a/include/xo/numeric/NumericOps.hpp +++ b/include/xo/numeric/NumericOps.hpp @@ -29,9 +29,10 @@ namespace xo { BinaryOp cmpeq, BinaryOp cmpne, BinaryOp cmplt, - BinaryOp cmple) + BinaryOp cmple, + BinaryOp cmpge) : multiply_{multiply}, divide_{divide}, add_{add}, subtract_{subtract}, - cmpeq_{cmpeq}, cmpne_{cmpne}, cmplt_{cmplt}, cmple_{cmple} {} + cmpeq_{cmpeq}, cmpne_{cmpne}, cmplt_{cmplt}, cmple_{cmple}, cmpge_{cmpge} {} BinaryOp multiply_ = nullptr; BinaryOp divide_ = nullptr; @@ -46,6 +47,8 @@ namespace xo { BinaryOp cmplt_ = nullptr; /** compare numerics (<=) **/ BinaryOp cmple_ = nullptr; + /** compare numerics (>=) **/ + BinaryOp cmpge_ = nullptr; }; template @@ -64,7 +67,8 @@ namespace xo { BinaryOp_Impl cmpeq, BinaryOp_Impl cmpne, BinaryOp_Impl cmplt, - BinaryOp_Impl cmple) { + BinaryOp_Impl cmple, + BinaryOp_Impl cmpge) { return AnonymizedNumericOps(reinterpret_cast(multiply), reinterpret_cast(divide), reinterpret_cast(add), @@ -72,7 +76,8 @@ namespace xo { reinterpret_cast(cmpeq), reinterpret_cast(cmpne), reinterpret_cast(cmplt), - reinterpret_cast(cmple)); + reinterpret_cast(cmple), + reinterpret_cast(cmpge)); } }; diff --git a/src/numeric/FloatIntegerOps.cpp b/src/numeric/FloatIntegerOps.cpp index c23d70f4..d2fedcfa 100644 --- a/src/numeric/FloatIntegerOps.cpp +++ b/src/numeric/FloatIntegerOps.cpp @@ -74,6 +74,14 @@ namespace xo { x->value() <= DFloat::value_type(y->value())); } + obj + FloatIntegerOps::cmp_greatequal(obj rcx, + DFloat * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), + x->value() >= DFloat::value_type(y->value())); + } + // ----- Integer op Float ----- obj @@ -136,6 +144,14 @@ namespace xo { DFloat::value_type(x->value()) <= y->value()); } + obj + IntegerFloatOps::cmp_greatequal(obj rcx, + DInteger * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), + DFloat::value_type(x->value()) >= y->value()); + } + } } diff --git a/src/numeric/FloatOps.cpp b/src/numeric/FloatOps.cpp index 8c59bb1f..a549c8ac 100644 --- a/src/numeric/FloatOps.cpp +++ b/src/numeric/FloatOps.cpp @@ -23,49 +23,64 @@ namespace xo { FloatOps::divide(obj rcx, DFloat * x, DFloat * y) { - return DFloat::box(rcx.allocator(), x->value() / y->value()); + return DFloat::box(rcx.allocator(), + x->value() / y->value()); } obj FloatOps::add(obj rcx, DFloat * x, DFloat * y) { - return DFloat::box(rcx.allocator(), x->value() + y->value()); + return DFloat::box(rcx.allocator(), + x->value() + y->value()); } obj FloatOps::subtract(obj rcx, DFloat * x, DFloat * y) { - return DFloat::box(rcx.allocator(), x->value() - y->value()); + return DFloat::box(rcx.allocator(), + x->value() - y->value()); } obj FloatOps::cmp_equal(obj rcx, DFloat * x, DFloat * y) { - return DBoolean::box(rcx.allocator(), x->value() == y->value()); + return DBoolean::box(rcx.allocator(), + x->value() == y->value()); } obj FloatOps::cmp_notequal(obj rcx, DFloat * x, DFloat * y) { - return DBoolean::box(rcx.allocator(), x->value() != y->value()); + return DBoolean::box(rcx.allocator(), + x->value() != y->value()); } obj FloatOps::cmp_less(obj rcx, DFloat * x, DFloat * y) { - return DBoolean::box(rcx.allocator(), x->value() < y->value()); + return DBoolean::box(rcx.allocator(), + x->value() < y->value()); } obj FloatOps::cmp_lessequal(obj rcx, DFloat * x, DFloat * y) { - return DBoolean::box(rcx.allocator(), x->value() <= y->value()); + return DBoolean::box(rcx.allocator(), + x->value() <= y->value()); + } + + obj + FloatOps::cmp_greatequal(obj rcx, + DFloat * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), + x->value() >= y->value()); } } } diff --git a/src/numeric/IntegerOps.cpp b/src/numeric/IntegerOps.cpp index 65874439..af67a5ee 100644 --- a/src/numeric/IntegerOps.cpp +++ b/src/numeric/IntegerOps.cpp @@ -69,6 +69,13 @@ namespace xo { return DBoolean::box(rcx.allocator(), x->value() <= y->value()); } + obj + IntegerOps::cmp_greatequal(obj rcx, + DInteger * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), x->value() >= y->value()); + } + } } diff --git a/src/numeric/NumericDispatch.cpp b/src/numeric/NumericDispatch.cpp index 42c507ee..0cc0af11 100644 --- a/src/numeric/NumericDispatch.cpp +++ b/src/numeric/NumericDispatch.cpp @@ -162,6 +162,18 @@ namespace xo { x, y); } + obj + NumericDispatch::cmp_greatequal(obj rcx, + obj x, + obj y) + { + return dispatch(rcx, + "NumericDispatch::cmp_great", + "incomparable types in x>=y", + &AnonymizedNumericOps::cmpge_, + x, y); + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/numeric/numeric_register_facets.cpp b/src/numeric/numeric_register_facets.cpp index fce3dc27..e70abe39 100644 --- a/src/numeric/numeric_register_facets.cpp +++ b/src/numeric/numeric_register_facets.cpp @@ -42,7 +42,8 @@ namespace xo { &FloatOps::cmp_equal, &FloatOps::cmp_notequal, &FloatOps::cmp_less, - &FloatOps::cmp_lessequal); + &FloatOps::cmp_lessequal, + &FloatOps::cmp_greatequal); NumericDispatch::instance().register_impl (&FloatIntegerOps::multiply, @@ -52,7 +53,8 @@ namespace xo { &FloatIntegerOps::cmp_equal, &FloatIntegerOps::cmp_notequal, &FloatIntegerOps::cmp_less, - &FloatIntegerOps::cmp_lessequal); + &FloatIntegerOps::cmp_lessequal, + &FloatIntegerOps::cmp_greatequal); NumericDispatch::instance().register_impl (&IntegerFloatOps::multiply, @@ -62,7 +64,8 @@ namespace xo { &IntegerFloatOps::cmp_equal, &IntegerFloatOps::cmp_notequal, &IntegerFloatOps::cmp_less, - &IntegerFloatOps::cmp_lessequal); + &IntegerFloatOps::cmp_lessequal, + &IntegerFloatOps::cmp_greatequal); NumericDispatch::instance().register_impl (&IntegerOps::multiply, @@ -72,7 +75,8 @@ namespace xo { &IntegerOps::cmp_equal, &IntegerOps::cmp_notequal, &IntegerOps::cmp_less, - &IntegerOps::cmp_lessequal); + &IntegerOps::cmp_lessequal, + &IntegerOps::cmp_greatequal); log && log(xtag("ANumeric.tseq", typeseq::id())); diff --git a/src/numeric/numeric_register_primitives.cpp b/src/numeric/numeric_register_primitives.cpp index ed5d777f..63c6f5fe 100644 --- a/src/numeric/numeric_register_primitives.cpp +++ b/src/numeric/numeric_register_primitives.cpp @@ -74,6 +74,8 @@ namespace xo { flags & InstallFlags::f_essential); ok = ok & install_aux(sink, mm, "_cmple", &NumericDispatch::cmp_lessequal, flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, mm, "_cmpge", &NumericDispatch::cmp_greatequal, + flags & InstallFlags::f_essential); return ok; } From c500a98722c10b286c38bb24541d658a78d5f1f3 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Fri, 13 Mar 2026 00:15:29 -0500 Subject: [PATCH 17/32] xo-reader2: + op> support --- include/xo/numeric/FloatIntegerOps.hpp | 4 ++++ include/xo/numeric/FloatOps.hpp | 2 ++ include/xo/numeric/IntegerOps.hpp | 2 ++ include/xo/numeric/NumericDispatch.hpp | 17 ++++++++++++----- include/xo/numeric/NumericOps.hpp | 9 ++++++++- src/numeric/FloatIntegerOps.cpp | 16 ++++++++++++++++ src/numeric/FloatOps.cpp | 8 ++++++++ src/numeric/IntegerOps.cpp | 7 +++++++ src/numeric/NumericDispatch.cpp | 14 +++++++++++++- src/numeric/numeric_register_facets.cpp | 4 ++++ src/numeric/numeric_register_primitives.cpp | 2 ++ 11 files changed, 78 insertions(+), 7 deletions(-) diff --git a/include/xo/numeric/FloatIntegerOps.hpp b/include/xo/numeric/FloatIntegerOps.hpp index 8508402f..972e5736 100644 --- a/include/xo/numeric/FloatIntegerOps.hpp +++ b/include/xo/numeric/FloatIntegerOps.hpp @@ -36,6 +36,8 @@ namespace xo { DFloat * x, DInteger * y); static obj cmp_lessequal(obj rcx, DFloat * x, DInteger * y); + static obj cmp_greater(obj rcx, + DFloat * x, DInteger * y); static obj cmp_greatequal(obj rcx, DFloat * x, DInteger * y); }; @@ -62,6 +64,8 @@ namespace xo { DInteger * x, DFloat * y); static obj cmp_lessequal(obj rcx, DInteger * x, DFloat * y); + static obj cmp_greater(obj rcx, + DInteger * x, DFloat * y); static obj cmp_greatequal(obj rcx, DInteger * x, DFloat * y); }; diff --git a/include/xo/numeric/FloatOps.hpp b/include/xo/numeric/FloatOps.hpp index 3eaabc9c..f9e6338c 100644 --- a/include/xo/numeric/FloatOps.hpp +++ b/include/xo/numeric/FloatOps.hpp @@ -35,6 +35,8 @@ namespace xo { DFloat * x, DFloat * y); static obj cmp_lessequal(obj rcx, DFloat * x, DFloat * y); + static obj cmp_greater(obj rcx, + DFloat * x, DFloat * y); static obj cmp_greatequal(obj rcx, DFloat * x, DFloat * y); }; diff --git a/include/xo/numeric/IntegerOps.hpp b/include/xo/numeric/IntegerOps.hpp index b8342555..90eb6e05 100644 --- a/include/xo/numeric/IntegerOps.hpp +++ b/include/xo/numeric/IntegerOps.hpp @@ -37,6 +37,8 @@ namespace xo { DInteger * x, DInteger * y); static obj cmp_lessequal(obj rcx, DInteger * x, DInteger * y); + static obj cmp_greater(obj rcx, + DInteger * x, DInteger * y); static obj cmp_greatequal(obj rcx, DInteger * x, DInteger * y); diff --git a/include/xo/numeric/NumericDispatch.hpp b/include/xo/numeric/NumericDispatch.hpp index 53b35b97..bd1f4bf4 100644 --- a/include/xo/numeric/NumericDispatch.hpp +++ b/include/xo/numeric/NumericDispatch.hpp @@ -93,27 +93,32 @@ namespace xo { obj x, obj y); - /** compare two numeric values for equality **/ + /** compare two numeric values for equality (==) **/ static obj cmp_equal(obj rcx, obj x, obj y); - /** compare two numeric values for inequality **/ + /** compare two numeric values for inequality (!~=) **/ static obj cmp_notequal(obj rcx, obj x, obj y); - /** compare two numeric values for less **/ + /** compare two numeric values for less (<) **/ static obj cmp_less(obj rcx, obj x, obj y); - /** compare two numeric values for less-or-equal **/ + /** compare two numeric values for less-or-equal (<=) **/ static obj cmp_lessequal(obj rcx, obj x, obj y); - /** compare two numeric values for greater-or-equal **/ + /** compare two numeric values for greater (>) **/ + static obj cmp_greater(obj rcx, + obj x, + obj y); + + /** compare two numeric values for greater-or-equal (>=) **/ static obj cmp_greatequal(obj rcx, obj x, obj y); @@ -135,6 +140,7 @@ namespace xo { typename NumericOps::BinaryOp_Impl cmpne_fn, typename NumericOps::BinaryOp_Impl cmplt_fn, typename NumericOps::BinaryOp_Impl cmple_fn, + typename NumericOps::BinaryOp_Impl cmpgt_fn, typename NumericOps::BinaryOp_Impl cmpge_fn) { KeyType key(typeseq::id().seqno(), @@ -150,6 +156,7 @@ namespace xo { cmpne_fn, cmplt_fn, cmple_fn, + cmpgt_fn, cmpge_fn); } diff --git a/include/xo/numeric/NumericOps.hpp b/include/xo/numeric/NumericOps.hpp index 5d983a98..ea25fb28 100644 --- a/include/xo/numeric/NumericOps.hpp +++ b/include/xo/numeric/NumericOps.hpp @@ -30,9 +30,12 @@ namespace xo { BinaryOp cmpne, BinaryOp cmplt, BinaryOp cmple, + BinaryOp cmpgt, BinaryOp cmpge) : multiply_{multiply}, divide_{divide}, add_{add}, subtract_{subtract}, - cmpeq_{cmpeq}, cmpne_{cmpne}, cmplt_{cmplt}, cmple_{cmple}, cmpge_{cmpge} {} + cmpeq_{cmpeq}, cmpne_{cmpne}, + cmplt_{cmplt}, cmple_{cmple}, + cmpgt_{cmpgt}, cmpge_{cmpge} {} BinaryOp multiply_ = nullptr; BinaryOp divide_ = nullptr; @@ -47,6 +50,8 @@ namespace xo { BinaryOp cmplt_ = nullptr; /** compare numerics (<=) **/ BinaryOp cmple_ = nullptr; + /** compare numerics (>) **/ + BinaryOp cmpgt_ = nullptr; /** compare numerics (>=) **/ BinaryOp cmpge_ = nullptr; }; @@ -68,6 +73,7 @@ namespace xo { BinaryOp_Impl cmpne, BinaryOp_Impl cmplt, BinaryOp_Impl cmple, + BinaryOp_Impl cmpgt, BinaryOp_Impl cmpge) { return AnonymizedNumericOps(reinterpret_cast(multiply), reinterpret_cast(divide), @@ -77,6 +83,7 @@ namespace xo { reinterpret_cast(cmpne), reinterpret_cast(cmplt), reinterpret_cast(cmple), + reinterpret_cast(cmpgt), reinterpret_cast(cmpge)); } }; diff --git a/src/numeric/FloatIntegerOps.cpp b/src/numeric/FloatIntegerOps.cpp index d2fedcfa..fab04cae 100644 --- a/src/numeric/FloatIntegerOps.cpp +++ b/src/numeric/FloatIntegerOps.cpp @@ -74,6 +74,14 @@ namespace xo { x->value() <= DFloat::value_type(y->value())); } + obj + FloatIntegerOps::cmp_greater(obj rcx, + DFloat * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), + x->value() > DFloat::value_type(y->value())); + } + obj FloatIntegerOps::cmp_greatequal(obj rcx, DFloat * x, DInteger * y) @@ -144,6 +152,14 @@ namespace xo { DFloat::value_type(x->value()) <= y->value()); } + obj + IntegerFloatOps::cmp_greater(obj rcx, + DInteger * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), + DFloat::value_type(x->value()) > y->value()); + } + obj IntegerFloatOps::cmp_greatequal(obj rcx, DInteger * x, DFloat * y) diff --git a/src/numeric/FloatOps.cpp b/src/numeric/FloatOps.cpp index a549c8ac..be522624 100644 --- a/src/numeric/FloatOps.cpp +++ b/src/numeric/FloatOps.cpp @@ -75,6 +75,14 @@ namespace xo { x->value() <= y->value()); } + obj + FloatOps::cmp_greater(obj rcx, + DFloat * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), + x->value() > y->value()); + } + obj FloatOps::cmp_greatequal(obj rcx, DFloat * x, DFloat * y) diff --git a/src/numeric/IntegerOps.cpp b/src/numeric/IntegerOps.cpp index af67a5ee..280e89d3 100644 --- a/src/numeric/IntegerOps.cpp +++ b/src/numeric/IntegerOps.cpp @@ -69,6 +69,13 @@ namespace xo { return DBoolean::box(rcx.allocator(), x->value() <= y->value()); } + obj + IntegerOps::cmp_greater(obj rcx, + DInteger * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), x->value() > y->value()); + } + obj IntegerOps::cmp_greatequal(obj rcx, DInteger * x, DInteger * y) diff --git a/src/numeric/NumericDispatch.cpp b/src/numeric/NumericDispatch.cpp index 0cc0af11..1ebdd414 100644 --- a/src/numeric/NumericDispatch.cpp +++ b/src/numeric/NumericDispatch.cpp @@ -162,13 +162,25 @@ namespace xo { x, y); } + obj + NumericDispatch::cmp_greater(obj rcx, + obj x, + obj y) + { + return dispatch(rcx, + "NumericDispatch::cmp_greater", + "incomparable types in x>y", + &AnonymizedNumericOps::cmpgt_, + x, y); + } + obj NumericDispatch::cmp_greatequal(obj rcx, obj x, obj y) { return dispatch(rcx, - "NumericDispatch::cmp_great", + "NumericDispatch::cmp_greatequal", "incomparable types in x>=y", &AnonymizedNumericOps::cmpge_, x, y); diff --git a/src/numeric/numeric_register_facets.cpp b/src/numeric/numeric_register_facets.cpp index e70abe39..7ef2555a 100644 --- a/src/numeric/numeric_register_facets.cpp +++ b/src/numeric/numeric_register_facets.cpp @@ -43,6 +43,7 @@ namespace xo { &FloatOps::cmp_notequal, &FloatOps::cmp_less, &FloatOps::cmp_lessequal, + &FloatOps::cmp_greater, &FloatOps::cmp_greatequal); NumericDispatch::instance().register_impl @@ -54,6 +55,7 @@ namespace xo { &FloatIntegerOps::cmp_notequal, &FloatIntegerOps::cmp_less, &FloatIntegerOps::cmp_lessequal, + &FloatIntegerOps::cmp_greater, &FloatIntegerOps::cmp_greatequal); NumericDispatch::instance().register_impl @@ -65,6 +67,7 @@ namespace xo { &IntegerFloatOps::cmp_notequal, &IntegerFloatOps::cmp_less, &IntegerFloatOps::cmp_lessequal, + &IntegerFloatOps::cmp_greater, &IntegerFloatOps::cmp_greatequal); NumericDispatch::instance().register_impl @@ -76,6 +79,7 @@ namespace xo { &IntegerOps::cmp_notequal, &IntegerOps::cmp_less, &IntegerOps::cmp_lessequal, + &IntegerOps::cmp_greater, &IntegerOps::cmp_greatequal); log && log(xtag("ANumeric.tseq", typeseq::id())); diff --git a/src/numeric/numeric_register_primitives.cpp b/src/numeric/numeric_register_primitives.cpp index 63c6f5fe..ff2749e3 100644 --- a/src/numeric/numeric_register_primitives.cpp +++ b/src/numeric/numeric_register_primitives.cpp @@ -74,6 +74,8 @@ namespace xo { flags & InstallFlags::f_essential); ok = ok & install_aux(sink, mm, "_cmple", &NumericDispatch::cmp_lessequal, flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, mm, "_cmpgt", &NumericDispatch::cmp_greater, + flags & InstallFlags::f_essential); ok = ok & install_aux(sink, mm, "_cmpge", &NumericDispatch::cmp_greatequal, flags & InstallFlags::f_essential); From 692a9a7f1beca2867bcdba3382290119603da82a Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 15 Mar 2026 09:47:14 -0500 Subject: [PATCH 18/32] xo-interpreter2 stack: modularize nth() primitive setup/install --- include/xo/numeric/NumericPrimitives.hpp | 4 ++++ .../xo/numeric/numeric_register_primitives.hpp | 4 ++-- src/numeric/NumericPrimitives.cpp | 16 ++++++++++++++++ src/numeric/numeric_register_primitives.cpp | 18 ++++++++++++------ 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/include/xo/numeric/NumericPrimitives.hpp b/include/xo/numeric/NumericPrimitives.hpp index a703af4a..54201f59 100644 --- a/include/xo/numeric/NumericPrimitives.hpp +++ b/include/xo/numeric/NumericPrimitives.hpp @@ -35,6 +35,10 @@ namespace xo { static DPrimitive_gco_2_gco_gco * make_cmplt_pm(obj mm); /** polymorphic (in both arguments) compare (<=) **/ static DPrimitive_gco_2_gco_gco * make_cmple_pm(obj mm); + /** polymorphic (in both arguments) compare (>) **/ + static DPrimitive_gco_2_gco_gco * make_cmpgt_pm(obj mm); + /** polymorphic (in both arguments) compare (>=) **/ + static DPrimitive_gco_2_gco_gco * make_cmpge_pm(obj mm); }; } } diff --git a/include/xo/numeric/numeric_register_primitives.hpp b/include/xo/numeric/numeric_register_primitives.hpp index 455d8b44..18a594be 100644 --- a/include/xo/numeric/numeric_register_primitives.hpp +++ b/include/xo/numeric/numeric_register_primitives.hpp @@ -10,8 +10,8 @@ namespace xo { namespace scm { - /** Register gc-aware (AGCObject,DRepr) combinations with garbage collector @p gc **/ - bool numeric_register_primitives(obj gc, + /** Register primitive factories with primitive registry **/ + bool numeric_register_primitives(obj mm, InstallSink sink, InstallFlags flags); } diff --git a/src/numeric/NumericPrimitives.cpp b/src/numeric/NumericPrimitives.cpp index e48c1a30..9ef0b979 100644 --- a/src/numeric/NumericPrimitives.cpp +++ b/src/numeric/NumericPrimitives.cpp @@ -68,6 +68,22 @@ namespace xo { &NumericDispatch::cmp_lessequal); } + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmpgt_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpgt", + &NumericDispatch::cmp_greater); + } + + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmpge_pm(obj mm) + { + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpge", + &NumericDispatch::cmp_greatequal); + } + + + } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/numeric/numeric_register_primitives.cpp b/src/numeric/numeric_register_primitives.cpp index ff2749e3..b2da4d9e 100644 --- a/src/numeric/numeric_register_primitives.cpp +++ b/src/numeric/numeric_register_primitives.cpp @@ -61,18 +61,24 @@ namespace xo { ok = ok & install_aux(sink, NumericPrimitives::make_divide_pm(mm), flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, mm, "_add", &NumericDispatch::add, + ok = ok & install_aux(sink, + NumericPrimitives::make_add_pm(mm), flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, mm, "_sub", &NumericDispatch::subtract, + ok = ok & install_aux(sink, + NumericPrimitives::make_subtract_pm(mm), flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, mm, "_cmpeq", &NumericDispatch::cmp_equal, + ok = ok & install_aux(sink, + NumericPrimitives::make_cmpeq_pm(mm), flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, mm, "_cmpne", &NumericDispatch::cmp_notequal, + ok = ok & install_aux(sink, + NumericPrimitives::make_cmpne_pm(mm), flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, mm, "_cmplt", &NumericDispatch::cmp_less, + ok = ok & install_aux(sink, + NumericPrimitives::make_cmplt_pm(mm), flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, mm, "_cmple", &NumericDispatch::cmp_lessequal, + ok = ok & install_aux(sink, + NumericPrimitives::make_cmple_pm(mm), flags & InstallFlags::f_essential); ok = ok & install_aux(sink, mm, "_cmpgt", &NumericDispatch::cmp_greater, flags & InstallFlags::f_essential); From 44c687dbfe6801a9b235ed3057573709952f9fec Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 16 Mar 2026 09:03:24 -0500 Subject: [PATCH 19/32] xo-interpreter2 stack: + dict type + pop more pm types --- include/xo/numeric/numeric_register_primitives.hpp | 1 + src/numeric/numeric_register_primitives.cpp | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/xo/numeric/numeric_register_primitives.hpp b/include/xo/numeric/numeric_register_primitives.hpp index 18a594be..c4b0bd7b 100644 --- a/include/xo/numeric/numeric_register_primitives.hpp +++ b/include/xo/numeric/numeric_register_primitives.hpp @@ -12,6 +12,7 @@ namespace xo { namespace scm { /** Register primitive factories with primitive registry **/ bool numeric_register_primitives(obj mm, + StringTable * stbl, InstallSink sink, InstallFlags flags); } diff --git a/src/numeric/numeric_register_primitives.cpp b/src/numeric/numeric_register_primitives.cpp index b2da4d9e..aa4a24d0 100644 --- a/src/numeric/numeric_register_primitives.cpp +++ b/src/numeric/numeric_register_primitives.cpp @@ -49,8 +49,11 @@ namespace xo { } bool - numeric_register_primitives(obj mm, InstallSink sink, InstallFlags flags) + numeric_register_primitives(obj mm, StringTable * stbl, + InstallSink sink, InstallFlags flags) { + (void)stbl; + scope log(XO_DEBUG(true)); bool ok = true; From 940cfb963acba225c461395a3f90053edf7d99a5 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 16 Mar 2026 13:29:48 -0500 Subject: [PATCH 20/32] xo-numeric: type decoration for multiply --- include/xo/numeric/NumericPrimitives.hpp | 3 ++- src/numeric/NumericPrimitives.cpp | 18 ++++++++++++++++-- src/numeric/numeric_register_primitives.cpp | 2 +- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/include/xo/numeric/NumericPrimitives.hpp b/include/xo/numeric/NumericPrimitives.hpp index 54201f59..8a1cd33d 100644 --- a/include/xo/numeric/NumericPrimitives.hpp +++ b/include/xo/numeric/NumericPrimitives.hpp @@ -18,7 +18,8 @@ namespace xo { public: /** polymorphic (in both arguments1) multiply **/ - static DPrimitive_gco_2_gco_gco * make_multiply_pm(obj mm); + static DPrimitive_gco_2_gco_gco * make_multiply_pm(obj mm, + StringTable * stbl); /** polymorphic (in both arguments) divide **/ static DPrimitive_gco_2_gco_gco * make_divide_pm(obj mm); diff --git a/src/numeric/NumericPrimitives.cpp b/src/numeric/NumericPrimitives.cpp index 9ef0b979..aeb7d8fb 100644 --- a/src/numeric/NumericPrimitives.cpp +++ b/src/numeric/NumericPrimitives.cpp @@ -5,6 +5,8 @@ #include "NumericPrimitives.hpp" #include "NumericDispatch.hpp" +#include +#include namespace xo { using xo::mm::AAllocator; @@ -13,9 +15,21 @@ namespace xo { namespace scm { DPrimitive_gco_2_gco_gco * - NumericPrimitives::make_multiply_pm(obj mm) + NumericPrimitives::make_multiply_pm(obj mm, + StringTable * stbl) { - return DPrimitive_gco_2_gco_gco::_make(mm, "_mul", + (void)stbl; + + // TODO: want to expand this to record schedule based on argument types. + // + // e.g. f64 x f64 -> f64 + + auto numeric_ty = DAtomicType::make(mm, Metatype::t_numeric()); + // #op+: numeric x numeric -> numeric + auto pm_ty = obj + (DFunctionType::_make(mm, numeric_ty, numeric_ty, numeric_ty)); + + return DPrimitive_gco_2_gco_gco::_make(mm, "_mul", pm_ty, &NumericDispatch::multiply); } diff --git a/src/numeric/numeric_register_primitives.cpp b/src/numeric/numeric_register_primitives.cpp index aa4a24d0..20eb5967 100644 --- a/src/numeric/numeric_register_primitives.cpp +++ b/src/numeric/numeric_register_primitives.cpp @@ -59,7 +59,7 @@ namespace xo { bool ok = true; ok = ok & install_aux(sink, - NumericPrimitives::make_multiply_pm(mm), + NumericPrimitives::make_multiply_pm(mm, stbl), flags & InstallFlags::f_essential); ok = ok & install_aux(sink, NumericPrimitives::make_divide_pm(mm), From 4039926d3363162406a0b1ab5cafc881f7dfb065 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 16 Mar 2026 13:51:51 -0500 Subject: [PATCH 21/32] xo-numeric: attach type to numeric primitives --- include/xo/numeric/NumericPrimitives.hpp | 28 +++-- src/numeric/NumericPrimitives.cpp | 114 ++++++++++++++++---- src/numeric/numeric_register_primitives.cpp | 22 ++-- 3 files changed, 127 insertions(+), 37 deletions(-) diff --git a/include/xo/numeric/NumericPrimitives.hpp b/include/xo/numeric/NumericPrimitives.hpp index 8a1cd33d..aec3ae84 100644 --- a/include/xo/numeric/NumericPrimitives.hpp +++ b/include/xo/numeric/NumericPrimitives.hpp @@ -20,26 +20,34 @@ namespace xo { /** polymorphic (in both arguments1) multiply **/ static DPrimitive_gco_2_gco_gco * make_multiply_pm(obj mm, StringTable * stbl); - /** polymorphic (in both arguments) divide **/ - static DPrimitive_gco_2_gco_gco * make_divide_pm(obj mm); + static DPrimitive_gco_2_gco_gco * make_divide_pm(obj mm, + StringTable * stbl); /** polymorphic (in both arguments) add **/ - static DPrimitive_gco_2_gco_gco * make_add_pm(obj mm); + static DPrimitive_gco_2_gco_gco * make_add_pm(obj mm, + StringTable * stbl); /** polymorphic (in both arguments) subtract **/ - static DPrimitive_gco_2_gco_gco * make_subtract_pm(obj mm); + static DPrimitive_gco_2_gco_gco * make_subtract_pm(obj mm, + StringTable * stbl); /** polymorphic (in both arguments) compare (==) **/ - static DPrimitive_gco_2_gco_gco * make_cmpeq_pm(obj mm); + static DPrimitive_gco_2_gco_gco * make_cmpeq_pm(obj mm, + StringTable * stbl); /** polymorphic (in both arguments) compare (!=) **/ - static DPrimitive_gco_2_gco_gco * make_cmpne_pm(obj mm); + static DPrimitive_gco_2_gco_gco * make_cmpne_pm(obj mm, + StringTable * stbl); /** polymorphic (in both arguments) compare (<) **/ - static DPrimitive_gco_2_gco_gco * make_cmplt_pm(obj mm); + static DPrimitive_gco_2_gco_gco * make_cmplt_pm(obj mm, + StringTable * stbl); /** polymorphic (in both arguments) compare (<=) **/ - static DPrimitive_gco_2_gco_gco * make_cmple_pm(obj mm); + static DPrimitive_gco_2_gco_gco * make_cmple_pm(obj mm, + StringTable * stbl); /** polymorphic (in both arguments) compare (>) **/ - static DPrimitive_gco_2_gco_gco * make_cmpgt_pm(obj mm); + static DPrimitive_gco_2_gco_gco * make_cmpgt_pm(obj mm, + StringTable * stbl); /** polymorphic (in both arguments) compare (>=) **/ - static DPrimitive_gco_2_gco_gco * make_cmpge_pm(obj mm); + static DPrimitive_gco_2_gco_gco * make_cmpge_pm(obj mm, + StringTable * stbl); }; } } diff --git a/src/numeric/NumericPrimitives.cpp b/src/numeric/NumericPrimitives.cpp index aeb7d8fb..decc8d60 100644 --- a/src/numeric/NumericPrimitives.cpp +++ b/src/numeric/NumericPrimitives.cpp @@ -34,65 +34,143 @@ namespace xo { } DPrimitive_gco_2_gco_gco * - NumericPrimitives::make_divide_pm(obj mm) + NumericPrimitives::make_divide_pm(obj mm, + StringTable * stbl) { - return DPrimitive_gco_2_gco_gco::_make(mm, "_div", + (void)stbl; + + auto numeric_ty = DAtomicType::make(mm, Metatype::t_numeric()); + // #op+: numeric x numeric -> numeric + auto pm_ty = obj + (DFunctionType::_make(mm, numeric_ty, numeric_ty, numeric_ty)); + + return DPrimitive_gco_2_gco_gco::_make(mm, "_div", pm_ty, &NumericDispatch::divide); } DPrimitive_gco_2_gco_gco * - NumericPrimitives::make_add_pm(obj mm) + NumericPrimitives::make_add_pm(obj mm, + StringTable * stbl) { - return DPrimitive_gco_2_gco_gco::_make(mm, "_add", + (void)stbl; + + auto numeric_ty = DAtomicType::make(mm, Metatype::t_numeric()); + // #op+: numeric x numeric -> numeric + auto pm_ty = obj + (DFunctionType::_make(mm, numeric_ty, numeric_ty, numeric_ty)); + + return DPrimitive_gco_2_gco_gco::_make(mm, "_add", pm_ty, &NumericDispatch::add); } DPrimitive_gco_2_gco_gco * - NumericPrimitives::make_subtract_pm(obj mm) + NumericPrimitives::make_subtract_pm(obj mm, + StringTable * stbl) { - return DPrimitive_gco_2_gco_gco::_make(mm, "_sub", + (void)stbl; + + auto numeric_ty = DAtomicType::make(mm, Metatype::t_numeric()); + // #op+: numeric x numeric -> numeric + auto pm_ty = obj + (DFunctionType::_make(mm, numeric_ty, numeric_ty, numeric_ty)); + + return DPrimitive_gco_2_gco_gco::_make(mm, "_sub", pm_ty, &NumericDispatch::subtract); } DPrimitive_gco_2_gco_gco * - NumericPrimitives::make_cmpeq_pm(obj mm) + NumericPrimitives::make_cmpeq_pm(obj mm, + StringTable * stbl) { - return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpeq", + (void)stbl; + + auto booleic_ty = DAtomicType::make(mm, Metatype::t_booleic()); + auto numeric_ty = DAtomicType::make(mm, Metatype::t_numeric()); + // #op==: numeric x numeric -> booleic + auto pm_ty = obj + (DFunctionType::_make(mm, booleic_ty, numeric_ty, numeric_ty)); + + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpeq", pm_ty, &NumericDispatch::cmp_equal); } DPrimitive_gco_2_gco_gco * - NumericPrimitives::make_cmpne_pm(obj mm) + NumericPrimitives::make_cmpne_pm(obj mm, + StringTable * stbl) { - return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpne", + (void)stbl; + + auto booleic_ty = DAtomicType::make(mm, Metatype::t_booleic()); + auto numeric_ty = DAtomicType::make(mm, Metatype::t_numeric()); + // #op!=: numeric x numeric -> booleic + auto pm_ty = obj + (DFunctionType::_make(mm, booleic_ty, numeric_ty, numeric_ty)); + + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpne", pm_ty, &NumericDispatch::cmp_notequal); } DPrimitive_gco_2_gco_gco * - NumericPrimitives::make_cmplt_pm(obj mm) + NumericPrimitives::make_cmplt_pm(obj mm, + StringTable * stbl) { - return DPrimitive_gco_2_gco_gco::_make(mm, "_cmplt", + (void)stbl; + + auto booleic_ty = DAtomicType::make(mm, Metatype::t_booleic()); + auto numeric_ty = DAtomicType::make(mm, Metatype::t_numeric()); + // #op!=: numeric x numeric -> booleic + auto pm_ty = obj + (DFunctionType::_make(mm, booleic_ty, numeric_ty, numeric_ty)); + + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmplt", pm_ty, &NumericDispatch::cmp_less); } DPrimitive_gco_2_gco_gco * - NumericPrimitives::make_cmple_pm(obj mm) + NumericPrimitives::make_cmple_pm(obj mm, + StringTable * stbl) { - return DPrimitive_gco_2_gco_gco::_make(mm, "_cmple", + (void)stbl; + + auto booleic_ty = DAtomicType::make(mm, Metatype::t_booleic()); + auto numeric_ty = DAtomicType::make(mm, Metatype::t_numeric()); + // #op!=: numeric x numeric -> booleic + auto pm_ty = obj + (DFunctionType::_make(mm, booleic_ty, numeric_ty, numeric_ty)); + + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmple", pm_ty, &NumericDispatch::cmp_lessequal); } DPrimitive_gco_2_gco_gco * - NumericPrimitives::make_cmpgt_pm(obj mm) + NumericPrimitives::make_cmpgt_pm(obj mm, + StringTable * stbl) { - return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpgt", + (void)stbl; + + auto booleic_ty = DAtomicType::make(mm, Metatype::t_booleic()); + auto numeric_ty = DAtomicType::make(mm, Metatype::t_numeric()); + // #op!=: numeric x numeric -> booleic + auto pm_ty = obj + (DFunctionType::_make(mm, booleic_ty, numeric_ty, numeric_ty)); + + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpgt", pm_ty, &NumericDispatch::cmp_greater); } DPrimitive_gco_2_gco_gco * - NumericPrimitives::make_cmpge_pm(obj mm) + NumericPrimitives::make_cmpge_pm(obj mm, + StringTable * stbl) { - return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpge", + (void)stbl; + + auto booleic_ty = DAtomicType::make(mm, Metatype::t_booleic()); + auto numeric_ty = DAtomicType::make(mm, Metatype::t_numeric()); + // #op!=: numeric x numeric -> booleic + auto pm_ty = obj + (DFunctionType::_make(mm, booleic_ty, numeric_ty, numeric_ty)); + + return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpge", pm_ty, &NumericDispatch::cmp_greatequal); } diff --git a/src/numeric/numeric_register_primitives.cpp b/src/numeric/numeric_register_primitives.cpp index 20eb5967..6150df9f 100644 --- a/src/numeric/numeric_register_primitives.cpp +++ b/src/numeric/numeric_register_primitives.cpp @@ -29,6 +29,7 @@ namespace xo { } } +#ifdef OBSOLETE bool install_aux(InstallSink sink, obj mm, std::string_view name, @@ -46,6 +47,7 @@ namespace xo { return true; } } +#endif } bool @@ -62,30 +64,32 @@ namespace xo { NumericPrimitives::make_multiply_pm(mm, stbl), flags & InstallFlags::f_essential); ok = ok & install_aux(sink, - NumericPrimitives::make_divide_pm(mm), + NumericPrimitives::make_divide_pm(mm, stbl), flags & InstallFlags::f_essential); ok = ok & install_aux(sink, - NumericPrimitives::make_add_pm(mm), + NumericPrimitives::make_add_pm(mm, stbl), flags & InstallFlags::f_essential); ok = ok & install_aux(sink, - NumericPrimitives::make_subtract_pm(mm), + NumericPrimitives::make_subtract_pm(mm, stbl), flags & InstallFlags::f_essential); ok = ok & install_aux(sink, - NumericPrimitives::make_cmpeq_pm(mm), + NumericPrimitives::make_cmpeq_pm(mm, stbl), flags & InstallFlags::f_essential); ok = ok & install_aux(sink, - NumericPrimitives::make_cmpne_pm(mm), + NumericPrimitives::make_cmpne_pm(mm, stbl), flags & InstallFlags::f_essential); ok = ok & install_aux(sink, - NumericPrimitives::make_cmplt_pm(mm), + NumericPrimitives::make_cmplt_pm(mm, stbl), flags & InstallFlags::f_essential); ok = ok & install_aux(sink, - NumericPrimitives::make_cmple_pm(mm), + NumericPrimitives::make_cmple_pm(mm, stbl), flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, mm, "_cmpgt", &NumericDispatch::cmp_greater, + ok = ok & install_aux(sink, + NumericPrimitives::make_cmpgt_pm(mm, stbl), flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, mm, "_cmpge", &NumericDispatch::cmp_greatequal, + ok = ok & install_aux(sink, + NumericPrimitives::make_cmpge_pm(mm, stbl), flags & InstallFlags::f_essential); return ok; From dc43feece04d3ca2c6b0cc0326bccc793a01589e Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 16 Mar 2026 14:09:03 -0500 Subject: [PATCH 22/32] xo-interpreter2 stack: use RuntimeContext to streamline setup --- include/xo/numeric/numeric_register_primitives.hpp | 5 +++-- src/numeric/numeric_register_primitives.cpp | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/xo/numeric/numeric_register_primitives.hpp b/include/xo/numeric/numeric_register_primitives.hpp index c4b0bd7b..5c68a51d 100644 --- a/include/xo/numeric/numeric_register_primitives.hpp +++ b/include/xo/numeric/numeric_register_primitives.hpp @@ -11,8 +11,9 @@ namespace xo { namespace scm { /** Register primitive factories with primitive registry **/ - bool numeric_register_primitives(obj mm, - StringTable * stbl, + bool numeric_register_primitives(obj rcx, + //obj mm, + //StringTable * stbl, InstallSink sink, InstallFlags flags); } diff --git a/src/numeric/numeric_register_primitives.cpp b/src/numeric/numeric_register_primitives.cpp index 6150df9f..08cb0fc9 100644 --- a/src/numeric/numeric_register_primitives.cpp +++ b/src/numeric/numeric_register_primitives.cpp @@ -51,10 +51,12 @@ namespace xo { } bool - numeric_register_primitives(obj mm, StringTable * stbl, + numeric_register_primitives(obj rcx, + //obj mm, StringTable * stbl, InstallSink sink, InstallFlags flags) { - (void)stbl; + obj mm = rcx.allocator(); + StringTable * stbl = rcx.stringtable(); scope log(XO_DEBUG(true)); From 884a6074d795b930caa67eec9a2138a9f48ed952 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 16 Mar 2026 14:41:28 -0500 Subject: [PATCH 23/32] xo-numeric: streamline setup --- include/xo/numeric/SetupNumeric.hpp | 25 +++ .../xo/numeric/numeric_register_facets.hpp | 16 -- .../numeric/numeric_register_primitives.hpp | 22 --- src/numeric/CMakeLists.txt | 3 +- src/numeric/SetupNumeric.cpp | 159 ++++++++++++++++++ src/numeric/init_numeric.cpp | 11 +- src/numeric/numeric_register_facets.cpp | 93 ---------- src/numeric/numeric_register_primitives.cpp | 102 ----------- 8 files changed, 190 insertions(+), 241 deletions(-) create mode 100644 include/xo/numeric/SetupNumeric.hpp delete mode 100644 include/xo/numeric/numeric_register_facets.hpp delete mode 100644 include/xo/numeric/numeric_register_primitives.hpp create mode 100644 src/numeric/SetupNumeric.cpp delete mode 100644 src/numeric/numeric_register_facets.cpp delete mode 100644 src/numeric/numeric_register_primitives.cpp diff --git a/include/xo/numeric/SetupNumeric.hpp b/include/xo/numeric/SetupNumeric.hpp new file mode 100644 index 00000000..b6fecd1f --- /dev/null +++ b/include/xo/numeric/SetupNumeric.hpp @@ -0,0 +1,25 @@ +/** @file SetupNumeric.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include "PrimitiveRegistry.hpp" +#include + +namespace xo { + namespace scm { + /** Setup numeric facet dispatch **/ + struct SetupNumeric { + public: + static bool register_facets(); + /** Register primitive factories with primitive registry **/ + static bool register_primitives(obj rcx, + InstallSink sink, + InstallFlags flags); + }; + } +} + +/* end SetupNumeric.hpp */ diff --git a/include/xo/numeric/numeric_register_facets.hpp b/include/xo/numeric/numeric_register_facets.hpp deleted file mode 100644 index 7beeb10e..00000000 --- a/include/xo/numeric/numeric_register_facets.hpp +++ /dev/null @@ -1,16 +0,0 @@ -/** @file numeric_register_facets.hpp - * - * @author Roland Conybeare, Feb 2026 - **/ - -#pragma once - -namespace xo { - namespace scm { - /** Setup numeric facet dispatch **/ - bool numeric_register_facets(); - - } -} - -/* end numeric_register_facets.hpp */ diff --git a/include/xo/numeric/numeric_register_primitives.hpp b/include/xo/numeric/numeric_register_primitives.hpp deleted file mode 100644 index 5c68a51d..00000000 --- a/include/xo/numeric/numeric_register_primitives.hpp +++ /dev/null @@ -1,22 +0,0 @@ -/** @file numeric_register_primitives.hpp - * - * @author Roland Conybeare, Mar 2026 - **/ - -#pragma once - -#include "PrimitiveRegistry.hpp" -#include - -namespace xo { - namespace scm { - /** Register primitive factories with primitive registry **/ - bool numeric_register_primitives(obj rcx, - //obj mm, - //StringTable * stbl, - InstallSink sink, - InstallFlags flags); - } -} - -/* end numeric_register_primitives.hpp */ diff --git a/src/numeric/CMakeLists.txt b/src/numeric/CMakeLists.txt index ca7dd6d5..256f9ad5 100644 --- a/src/numeric/CMakeLists.txt +++ b/src/numeric/CMakeLists.txt @@ -3,8 +3,7 @@ set(SELF_LIB xo_numeric) set(SELF_SRCS init_numeric.cpp - numeric_register_facets.cpp - numeric_register_primitives.cpp + SetupNumeric.cpp NumericPrimitives.cpp NumericDispatch.cpp INumeric_Any.cpp diff --git a/src/numeric/SetupNumeric.cpp b/src/numeric/SetupNumeric.cpp new file mode 100644 index 00000000..c5920505 --- /dev/null +++ b/src/numeric/SetupNumeric.cpp @@ -0,0 +1,159 @@ +/** @file SetupNumeric.cpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#include "SetupNumeric.hpp" +#include "NumericDispatch.hpp" +#include "Numeric.hpp" +#include "NumericPrimitives.hpp" +#include "NumericDispatch.hpp" + +#include "FloatIntegerOps.hpp" +#include "FloatOps.hpp" +#include "float/INumeric_DFloat.hpp" + +#include "IntegerOps.hpp" +#include "integer/INumeric_DInteger.hpp" + +#include + +#include +#include + +#include +#include +#include + +namespace xo { + using xo::mm::AAllocator; + using xo::facet::FacetRegistry; + using xo::reflect::typeseq; + + namespace scm { + bool + SetupNumeric::register_facets() + { + scope log(XO_DEBUG(true)); + + FacetRegistry::register_impl(); + + NumericDispatch::instance().register_impl + (&FloatOps::multiply, + &FloatOps::divide, + &FloatOps::add, + &FloatOps::subtract, + &FloatOps::cmp_equal, + &FloatOps::cmp_notequal, + &FloatOps::cmp_less, + &FloatOps::cmp_lessequal, + &FloatOps::cmp_greater, + &FloatOps::cmp_greatequal); + + NumericDispatch::instance().register_impl + (&FloatIntegerOps::multiply, + &FloatIntegerOps::divide, + &FloatIntegerOps::add, + &FloatIntegerOps::subtract, + &FloatIntegerOps::cmp_equal, + &FloatIntegerOps::cmp_notequal, + &FloatIntegerOps::cmp_less, + &FloatIntegerOps::cmp_lessequal, + &FloatIntegerOps::cmp_greater, + &FloatIntegerOps::cmp_greatequal); + + NumericDispatch::instance().register_impl + (&IntegerFloatOps::multiply, + &IntegerFloatOps::divide, + &IntegerFloatOps::add, + &IntegerFloatOps::subtract, + &IntegerFloatOps::cmp_equal, + &IntegerFloatOps::cmp_notequal, + &IntegerFloatOps::cmp_less, + &IntegerFloatOps::cmp_lessequal, + &IntegerFloatOps::cmp_greater, + &IntegerFloatOps::cmp_greatequal); + + NumericDispatch::instance().register_impl + (&IntegerOps::multiply, + &IntegerOps::divide, + &IntegerOps::add, + &IntegerOps::subtract, + &IntegerOps::cmp_equal, + &IntegerOps::cmp_notequal, + &IntegerOps::cmp_less, + &IntegerOps::cmp_lessequal, + &IntegerOps::cmp_greater, + &IntegerOps::cmp_greatequal); + + log && log(xtag("ANumeric.tseq", typeseq::id())); + + return true; + } + + namespace { + bool install_aux(InstallSink sink, + DPrimitive_gco_2_gco_gco * pm, + InstallFlags flags) + { + if (flags != InstallFlags::f_none) { + return sink(pm->name(), + pm->fn_td(), + obj(pm), + flags); + } else { + return true; + } + } + } + + bool + SetupNumeric::register_primitives(obj rcx, + InstallSink sink, + InstallFlags flags) + { + obj mm = rcx.allocator(); + StringTable * stbl = rcx.stringtable(); + + scope log(XO_DEBUG(true)); + + bool ok = true; + + ok = ok & install_aux(sink, + NumericPrimitives::make_multiply_pm(mm, stbl), + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, + NumericPrimitives::make_divide_pm(mm, stbl), + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, + NumericPrimitives::make_add_pm(mm, stbl), + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, + NumericPrimitives::make_subtract_pm(mm, stbl), + flags & InstallFlags::f_essential); + + ok = ok & install_aux(sink, + NumericPrimitives::make_cmpeq_pm(mm, stbl), + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, + NumericPrimitives::make_cmpne_pm(mm, stbl), + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, + NumericPrimitives::make_cmplt_pm(mm, stbl), + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, + NumericPrimitives::make_cmple_pm(mm, stbl), + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, + NumericPrimitives::make_cmpgt_pm(mm, stbl), + flags & InstallFlags::f_essential); + ok = ok & install_aux(sink, + NumericPrimitives::make_cmpge_pm(mm, stbl), + flags & InstallFlags::f_essential); + + return ok; + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end SetupNumeric.cpp */ diff --git a/src/numeric/init_numeric.cpp b/src/numeric/init_numeric.cpp index faa678a0..86105ec6 100644 --- a/src/numeric/init_numeric.cpp +++ b/src/numeric/init_numeric.cpp @@ -4,22 +4,21 @@ **/ #include "init_numeric.hpp" +#include "SetupNumeric.hpp" #include #include "Subsystem.hpp" -#include "numeric_register_facets.hpp" -#include "numeric_register_primitives.hpp" namespace xo { - using xo::scm::numeric_register_facets; - using xo::scm::numeric_register_primitives; + using xo::scm::SetupNumeric; + //using xo::scm::numeric_register_primitives; using xo::scm::PrimitiveRegistry; void InitSubsys::init() { - numeric_register_facets(); + SetupNumeric::register_facets(); - PrimitiveRegistry::instance().register_primitives(&numeric_register_primitives); + PrimitiveRegistry::instance().register_primitives(&SetupNumeric::register_primitives); } diff --git a/src/numeric/numeric_register_facets.cpp b/src/numeric/numeric_register_facets.cpp deleted file mode 100644 index 7ef2555a..00000000 --- a/src/numeric/numeric_register_facets.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/** @file numeric_register_facets.cpp - * - * @author Roland Conybeare, Feb 2026 - **/ - -#include "numeric_register_facets.hpp" -#include "NumericDispatch.hpp" -#include "Numeric.hpp" - -#include "FloatIntegerOps.hpp" -#include "FloatOps.hpp" -#include "float/INumeric_DFloat.hpp" - -#include "IntegerOps.hpp" -#include "integer/INumeric_DInteger.hpp" - -#include -#include - -#include -#include -#include - -namespace xo { - using xo::facet::FacetRegistry; - using xo::reflect::typeseq; - - namespace scm { - - bool - numeric_register_facets() - { - scope log(XO_DEBUG(true)); - - FacetRegistry::register_impl(); - - NumericDispatch::instance().register_impl - (&FloatOps::multiply, - &FloatOps::divide, - &FloatOps::add, - &FloatOps::subtract, - &FloatOps::cmp_equal, - &FloatOps::cmp_notequal, - &FloatOps::cmp_less, - &FloatOps::cmp_lessequal, - &FloatOps::cmp_greater, - &FloatOps::cmp_greatequal); - - NumericDispatch::instance().register_impl - (&FloatIntegerOps::multiply, - &FloatIntegerOps::divide, - &FloatIntegerOps::add, - &FloatIntegerOps::subtract, - &FloatIntegerOps::cmp_equal, - &FloatIntegerOps::cmp_notequal, - &FloatIntegerOps::cmp_less, - &FloatIntegerOps::cmp_lessequal, - &FloatIntegerOps::cmp_greater, - &FloatIntegerOps::cmp_greatequal); - - NumericDispatch::instance().register_impl - (&IntegerFloatOps::multiply, - &IntegerFloatOps::divide, - &IntegerFloatOps::add, - &IntegerFloatOps::subtract, - &IntegerFloatOps::cmp_equal, - &IntegerFloatOps::cmp_notequal, - &IntegerFloatOps::cmp_less, - &IntegerFloatOps::cmp_lessequal, - &IntegerFloatOps::cmp_greater, - &IntegerFloatOps::cmp_greatequal); - - NumericDispatch::instance().register_impl - (&IntegerOps::multiply, - &IntegerOps::divide, - &IntegerOps::add, - &IntegerOps::subtract, - &IntegerOps::cmp_equal, - &IntegerOps::cmp_notequal, - &IntegerOps::cmp_less, - &IntegerOps::cmp_lessequal, - &IntegerOps::cmp_greater, - &IntegerOps::cmp_greatequal); - - log && log(xtag("ANumeric.tseq", typeseq::id())); - - return true; - } - - } /*namespace scm*/ -} /*namespace xo*/ - -/* end numeric_register_facets.cpp */ diff --git a/src/numeric/numeric_register_primitives.cpp b/src/numeric/numeric_register_primitives.cpp deleted file mode 100644 index 08cb0fc9..00000000 --- a/src/numeric/numeric_register_primitives.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/** @file numeric_register_primitives.cpp - * - * @author Roland Conybeare, Mar 2026 - **/ - -#include "numeric_register_primitives.hpp" -#include "NumericPrimitives.hpp" -#include "NumericDispatch.hpp" -#include -#include - -namespace xo { - using xo::mm::AAllocator; - using xo::scope; - - namespace scm { - namespace { - bool install_aux(InstallSink sink, - DPrimitive_gco_2_gco_gco * pm, - InstallFlags flags) - { - if (flags != InstallFlags::f_none) { - return sink(pm->name(), - pm->fn_td(), - obj(pm), - flags); - } else { - return true; - } - } - -#ifdef OBSOLETE - bool install_aux(InstallSink sink, - obj mm, - std::string_view name, - obj (*impl)(obj rcx, - obj x, - obj y), - InstallFlags flags) - { - if (flags != InstallFlags::f_none) { - auto pm - = DPrimitive_gco_2_gco_gco::_make(mm, name, impl); - - return install_aux(sink, pm, flags); - } else { - return true; - } - } -#endif - } - - bool - numeric_register_primitives(obj rcx, - //obj mm, StringTable * stbl, - InstallSink sink, InstallFlags flags) - { - obj mm = rcx.allocator(); - StringTable * stbl = rcx.stringtable(); - - scope log(XO_DEBUG(true)); - - bool ok = true; - - ok = ok & install_aux(sink, - NumericPrimitives::make_multiply_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_divide_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_add_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_subtract_pm(mm, stbl), - flags & InstallFlags::f_essential); - - ok = ok & install_aux(sink, - NumericPrimitives::make_cmpeq_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_cmpne_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_cmplt_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_cmple_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_cmpgt_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_cmpge_pm(mm, stbl), - flags & InstallFlags::f_essential); - - return ok; - } - } -} /*namespace xo*/ - -/* end numeric_register_primitives.cpp */ From f4d00d9e17bfdca1c22b8537407b0cf5d107922a Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 16 Mar 2026 20:18:52 -0500 Subject: [PATCH 24/32] xo-interpreter2: streamline pm setup --- src/numeric/SetupNumeric.cpp | 87 +++++++++++++++++------------------- 1 file changed, 40 insertions(+), 47 deletions(-) diff --git a/src/numeric/SetupNumeric.cpp b/src/numeric/SetupNumeric.cpp index c5920505..75a1f1de 100644 --- a/src/numeric/SetupNumeric.cpp +++ b/src/numeric/SetupNumeric.cpp @@ -91,22 +91,6 @@ namespace xo { return true; } - namespace { - bool install_aux(InstallSink sink, - DPrimitive_gco_2_gco_gco * pm, - InstallFlags flags) - { - if (flags != InstallFlags::f_none) { - return sink(pm->name(), - pm->fn_td(), - obj(pm), - flags); - } else { - return true; - } - } - } - bool SetupNumeric::register_primitives(obj rcx, InstallSink sink, @@ -119,37 +103,46 @@ namespace xo { bool ok = true; - ok = ok & install_aux(sink, - NumericPrimitives::make_multiply_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_divide_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_add_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_subtract_pm(mm, stbl), - flags & InstallFlags::f_essential); - - ok = ok & install_aux(sink, - NumericPrimitives::make_cmpeq_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_cmpne_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_cmplt_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_cmple_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_cmpgt_pm(mm, stbl), - flags & InstallFlags::f_essential); - ok = ok & install_aux(sink, - NumericPrimitives::make_cmpge_pm(mm, stbl), - flags & InstallFlags::f_essential); + ok = ok & (PrimitiveRegistry::install_aux + (sink, + NumericPrimitives::make_multiply_pm(mm, stbl), + flags & InstallFlags::f_essential)); + ok = ok & (PrimitiveRegistry::install_aux + (sink, + NumericPrimitives::make_divide_pm(mm, stbl), + flags & InstallFlags::f_essential)); + ok = ok & (PrimitiveRegistry::install_aux + (sink, + NumericPrimitives::make_add_pm(mm, stbl), + flags & InstallFlags::f_essential)); + ok = ok & (PrimitiveRegistry::install_aux + (sink, + NumericPrimitives::make_subtract_pm(mm, stbl), + flags & InstallFlags::f_essential)); + ok = ok & (PrimitiveRegistry::install_aux + (sink, + NumericPrimitives::make_cmpeq_pm(mm, stbl), + flags & InstallFlags::f_essential)); + ok = ok & (PrimitiveRegistry::install_aux + (sink, + NumericPrimitives::make_cmpne_pm(mm, stbl), + flags & InstallFlags::f_essential)); + ok = ok & (PrimitiveRegistry::install_aux + (sink, + NumericPrimitives::make_cmplt_pm(mm, stbl), + flags & InstallFlags::f_essential)); + ok = ok & (PrimitiveRegistry::install_aux + (sink, + NumericPrimitives::make_cmple_pm(mm, stbl), + flags & InstallFlags::f_essential)); + ok = ok & (PrimitiveRegistry::install_aux + (sink, + NumericPrimitives::make_cmpgt_pm(mm, stbl), + flags & InstallFlags::f_essential)); + ok = ok & (PrimitiveRegistry::install_aux + (sink, + NumericPrimitives::make_cmpge_pm(mm, stbl), + flags & InstallFlags::f_essential)); return ok; } From 335c04a834609b65921be385854a4cfb29f6d45e Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Tue, 24 Mar 2026 22:01:28 -0400 Subject: [PATCH 25/32] xo-numeric: cosmetic: add comments to label essential primitives --- src/numeric/SetupNumeric.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/numeric/SetupNumeric.cpp b/src/numeric/SetupNumeric.cpp index 75a1f1de..d61d6edc 100644 --- a/src/numeric/SetupNumeric.cpp +++ b/src/numeric/SetupNumeric.cpp @@ -103,42 +103,52 @@ namespace xo { bool ok = true; + /* "_mul" */ ok = ok & (PrimitiveRegistry::install_aux (sink, NumericPrimitives::make_multiply_pm(mm, stbl), flags & InstallFlags::f_essential)); + /* "_div" */ ok = ok & (PrimitiveRegistry::install_aux (sink, NumericPrimitives::make_divide_pm(mm, stbl), flags & InstallFlags::f_essential)); + /* "_add" */ ok = ok & (PrimitiveRegistry::install_aux (sink, NumericPrimitives::make_add_pm(mm, stbl), flags & InstallFlags::f_essential)); + /* "_sub" */ ok = ok & (PrimitiveRegistry::install_aux (sink, NumericPrimitives::make_subtract_pm(mm, stbl), flags & InstallFlags::f_essential)); + /* "_cmpeq" */ ok = ok & (PrimitiveRegistry::install_aux (sink, NumericPrimitives::make_cmpeq_pm(mm, stbl), flags & InstallFlags::f_essential)); + /* "_cmpne" */ ok = ok & (PrimitiveRegistry::install_aux (sink, NumericPrimitives::make_cmpne_pm(mm, stbl), flags & InstallFlags::f_essential)); + /* "_cmplt" */ ok = ok & (PrimitiveRegistry::install_aux (sink, NumericPrimitives::make_cmplt_pm(mm, stbl), flags & InstallFlags::f_essential)); + /* "_cmple" */ ok = ok & (PrimitiveRegistry::install_aux (sink, NumericPrimitives::make_cmple_pm(mm, stbl), flags & InstallFlags::f_essential)); + /* "_cmpgt" */ ok = ok & (PrimitiveRegistry::install_aux (sink, NumericPrimitives::make_cmpgt_pm(mm, stbl), flags & InstallFlags::f_essential)); + /* "_cmpge" */ ok = ok & (PrimitiveRegistry::install_aux (sink, NumericPrimitives::make_cmpge_pm(mm, stbl), From b3fbddcf3ea2ebe770b8893945669eae7f096009 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Tue, 24 Mar 2026 22:16:24 -0400 Subject: [PATCH 26/32] xo-numeric: cosmetic: drop debug --- src/numeric/SetupNumeric.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/numeric/SetupNumeric.cpp b/src/numeric/SetupNumeric.cpp index d61d6edc..58254fc2 100644 --- a/src/numeric/SetupNumeric.cpp +++ b/src/numeric/SetupNumeric.cpp @@ -99,7 +99,7 @@ namespace xo { obj mm = rcx.allocator(); StringTable * stbl = rcx.stringtable(); - scope log(XO_DEBUG(true)); + scope log(XO_DEBUG(false)); bool ok = true; From 4601e824bc7d7614316d967a889571b7318e713a Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 25 Mar 2026 17:11:46 -0400 Subject: [PATCH 27/32] xo-reader2 stack: refactor for ssm file location --- src/numeric/NumericPrimitives.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/numeric/NumericPrimitives.cpp b/src/numeric/NumericPrimitives.cpp index decc8d60..8515e9d4 100644 --- a/src/numeric/NumericPrimitives.cpp +++ b/src/numeric/NumericPrimitives.cpp @@ -24,10 +24,14 @@ namespace xo { // // e.g. f64 x f64 -> f64 +#ifdef NOPE auto numeric_ty = DAtomicType::make(mm, Metatype::t_numeric()); // #op+: numeric x numeric -> numeric auto pm_ty = obj (DFunctionType::_make(mm, numeric_ty, numeric_ty, numeric_ty)); +#endif + + auto pm_ty = obj(); return DPrimitive_gco_2_gco_gco::_make(mm, "_mul", pm_ty, &NumericDispatch::multiply); From d288c4ff1efa676276bc866772d352024c252b03 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 25 Mar 2026 17:52:39 -0400 Subject: [PATCH 28/32] xo-reader2 stack: constants for operator primitive names --- include/xo/numeric/NumericPrimitives.hpp | 25 ++++++++++++++++++++++++ src/numeric/NumericPrimitives.cpp | 20 +++++++++---------- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/include/xo/numeric/NumericPrimitives.hpp b/include/xo/numeric/NumericPrimitives.hpp index aec3ae84..51c614f1 100644 --- a/include/xo/numeric/NumericPrimitives.hpp +++ b/include/xo/numeric/NumericPrimitives.hpp @@ -17,31 +17,56 @@ namespace xo { using AAllocator = xo::mm::AAllocator; public: + /** name for multiply primitive. Used for op* **/ + static constexpr const char * c_multiply_pm_name = "_mul"; /** polymorphic (in both arguments1) multiply **/ static DPrimitive_gco_2_gco_gco * make_multiply_pm(obj mm, StringTable * stbl); + + /** name for divide primitives. Used for op/ **/ + static constexpr const char * c_divide_pm_name = "_div"; /** polymorphic (in both arguments) divide **/ static DPrimitive_gco_2_gco_gco * make_divide_pm(obj mm, StringTable * stbl); + + /** name for add primitives. Used for op+ **/ + static constexpr const char * c_add_pm_name = "_add"; /** polymorphic (in both arguments) add **/ static DPrimitive_gco_2_gco_gco * make_add_pm(obj mm, StringTable * stbl); + + /** name for sub primitives. Used for op- **/ + static constexpr const char * c_sub_pm_name = "_sub"; /** polymorphic (in both arguments) subtract **/ static DPrimitive_gco_2_gco_gco * make_subtract_pm(obj mm, StringTable * stbl); + /** name for equality-comparison primitive. Used for op== **/ + static constexpr const char * c_cmpeq_pm_name = "_cmpeq"; /** polymorphic (in both arguments) compare (==) **/ static DPrimitive_gco_2_gco_gco * make_cmpeq_pm(obj mm, StringTable * stbl); + + /** name for inequality-comparison prmitive. Used for op!= **/ + static constexpr const char * c_cmpne_pm_name = "_cmpne"; /** polymorphic (in both arguments) compare (!=) **/ static DPrimitive_gco_2_gco_gco * make_cmpne_pm(obj mm, StringTable * stbl); + + /** name for less-comparison primitive. Used for op< **/ + static constexpr const char * c_cmplt_pm_name = "_cmplt"; /** polymorphic (in both arguments) compare (<) **/ static DPrimitive_gco_2_gco_gco * make_cmplt_pm(obj mm, StringTable * stbl); + + /** name for lesser-or-equal-comparison primitive. Used for op<= **/ + static constexpr const char * c_cmple_pm_name = "_cmple"; /** polymorphic (in both arguments) compare (<=) **/ static DPrimitive_gco_2_gco_gco * make_cmple_pm(obj mm, StringTable * stbl); + + /** name for greater-comparison primitive. Used for op> **/ + static constexpr const char * c_cmpgt_pm_name = "_cmpgt"; /** polymorphic (in both arguments) compare (>) **/ static DPrimitive_gco_2_gco_gco * make_cmpgt_pm(obj mm, StringTable * stbl); diff --git a/src/numeric/NumericPrimitives.cpp b/src/numeric/NumericPrimitives.cpp index 8515e9d4..0104f4cb 100644 --- a/src/numeric/NumericPrimitives.cpp +++ b/src/numeric/NumericPrimitives.cpp @@ -33,7 +33,7 @@ namespace xo { auto pm_ty = obj(); - return DPrimitive_gco_2_gco_gco::_make(mm, "_mul", pm_ty, + return DPrimitive_gco_2_gco_gco::_make(mm, c_multiply_pm_name, pm_ty, &NumericDispatch::multiply); } @@ -48,7 +48,7 @@ namespace xo { auto pm_ty = obj (DFunctionType::_make(mm, numeric_ty, numeric_ty, numeric_ty)); - return DPrimitive_gco_2_gco_gco::_make(mm, "_div", pm_ty, + return DPrimitive_gco_2_gco_gco::_make(mm, c_divide_pm_name, pm_ty, &NumericDispatch::divide); } @@ -63,7 +63,7 @@ namespace xo { auto pm_ty = obj (DFunctionType::_make(mm, numeric_ty, numeric_ty, numeric_ty)); - return DPrimitive_gco_2_gco_gco::_make(mm, "_add", pm_ty, + return DPrimitive_gco_2_gco_gco::_make(mm, c_add_pm_name, pm_ty, &NumericDispatch::add); } @@ -78,7 +78,7 @@ namespace xo { auto pm_ty = obj (DFunctionType::_make(mm, numeric_ty, numeric_ty, numeric_ty)); - return DPrimitive_gco_2_gco_gco::_make(mm, "_sub", pm_ty, + return DPrimitive_gco_2_gco_gco::_make(mm, c_sub_pm_name, pm_ty, &NumericDispatch::subtract); } @@ -94,7 +94,7 @@ namespace xo { auto pm_ty = obj (DFunctionType::_make(mm, booleic_ty, numeric_ty, numeric_ty)); - return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpeq", pm_ty, + return DPrimitive_gco_2_gco_gco::_make(mm, c_cmpeq_pm_name, pm_ty, &NumericDispatch::cmp_equal); } @@ -110,7 +110,7 @@ namespace xo { auto pm_ty = obj (DFunctionType::_make(mm, booleic_ty, numeric_ty, numeric_ty)); - return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpne", pm_ty, + return DPrimitive_gco_2_gco_gco::_make(mm, c_cmpne_pm_name, pm_ty, &NumericDispatch::cmp_notequal); } @@ -126,7 +126,7 @@ namespace xo { auto pm_ty = obj (DFunctionType::_make(mm, booleic_ty, numeric_ty, numeric_ty)); - return DPrimitive_gco_2_gco_gco::_make(mm, "_cmplt", pm_ty, + return DPrimitive_gco_2_gco_gco::_make(mm, c_cmplt_pm_name, pm_ty, &NumericDispatch::cmp_less); } @@ -142,7 +142,7 @@ namespace xo { auto pm_ty = obj (DFunctionType::_make(mm, booleic_ty, numeric_ty, numeric_ty)); - return DPrimitive_gco_2_gco_gco::_make(mm, "_cmple", pm_ty, + return DPrimitive_gco_2_gco_gco::_make(mm, c_cmple_pm_name, pm_ty, &NumericDispatch::cmp_lessequal); } @@ -158,7 +158,7 @@ namespace xo { auto pm_ty = obj (DFunctionType::_make(mm, booleic_ty, numeric_ty, numeric_ty)); - return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpgt", pm_ty, + return DPrimitive_gco_2_gco_gco::_make(mm, c_cmpgt_pm_name, pm_ty, &NumericDispatch::cmp_greater); } @@ -174,7 +174,7 @@ namespace xo { auto pm_ty = obj (DFunctionType::_make(mm, booleic_ty, numeric_ty, numeric_ty)); - return DPrimitive_gco_2_gco_gco::_make(mm, "_cmpge", pm_ty, + return DPrimitive_gco_2_gco_gco::_make(mm, c_cmpge_pm_name, pm_ty, &NumericDispatch::cmp_greatequal); } From 9e88672ad4b78ec92c7b8d2a1ec0c50cfda51c62 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 25 Mar 2026 19:31:59 -0400 Subject: [PATCH 29/32] xo-interpreter2 stack: VSM as AGCObject for virtual root --- include/xo/numeric/NumericPrimitives.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/xo/numeric/NumericPrimitives.hpp b/include/xo/numeric/NumericPrimitives.hpp index 51c614f1..a1e047f0 100644 --- a/include/xo/numeric/NumericPrimitives.hpp +++ b/include/xo/numeric/NumericPrimitives.hpp @@ -70,6 +70,9 @@ namespace xo { /** polymorphic (in both arguments) compare (>) **/ static DPrimitive_gco_2_gco_gco * make_cmpgt_pm(obj mm, StringTable * stbl); + + /** name for greater-or-equal-comparison primitive. Used for op>= **/ + static constexpr const char * c_cmpge_pm_name = "_cmpge"; /** polymorphic (in both arguments) compare (>=) **/ static DPrimitive_gco_2_gco_gco * make_cmpge_pm(obj mm, StringTable * stbl); From 5950a45483ecf26931b2df1bf05925efb4d16186 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sat, 28 Mar 2026 09:45:36 -0400 Subject: [PATCH 30/32] xo-numeric: restore numeric function type --- src/numeric/NumericPrimitives.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/numeric/NumericPrimitives.cpp b/src/numeric/NumericPrimitives.cpp index 0104f4cb..9697cc9b 100644 --- a/src/numeric/NumericPrimitives.cpp +++ b/src/numeric/NumericPrimitives.cpp @@ -24,14 +24,10 @@ namespace xo { // // e.g. f64 x f64 -> f64 -#ifdef NOPE auto numeric_ty = DAtomicType::make(mm, Metatype::t_numeric()); // #op+: numeric x numeric -> numeric auto pm_ty = obj (DFunctionType::_make(mm, numeric_ty, numeric_ty, numeric_ty)); -#endif - - auto pm_ty = obj(); return DPrimitive_gco_2_gco_gco::_make(mm, c_multiply_pm_name, pm_ty, &NumericDispatch::multiply); From 4dc673916796a985d3e1ef16395f8528e31583d2 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sat, 4 Apr 2026 16:33:35 -0400 Subject: [PATCH 31/32] refactor: rename shallow_copy -> shallow_move + streamline Use RCollector.std_copy_for where appropriate --- include/xo/numeric/detail/ANumeric.hpp | 5 +++++ include/xo/numeric/detail/RNumeric.hpp | 1 + 2 files changed, 6 insertions(+) diff --git a/include/xo/numeric/detail/ANumeric.hpp b/include/xo/numeric/detail/ANumeric.hpp index bda27456..7c8e0c99 100644 --- a/include/xo/numeric/detail/ANumeric.hpp +++ b/include/xo/numeric/detail/ANumeric.hpp @@ -42,6 +42,11 @@ public: /** @defgroup scm-numeric-methods **/ ///@{ // const methods + /** An uninitialized ANumeric instance will have zero vtable pointer (per {linux,osx} abi). + * Use case for this is narrow. We go to some lengths to avoid null vtable pointers. For example + * obj will have non-null vtable (via IFacet_Any) with all methods terminating. + **/ + bool _has_null_vptr() const noexcept { return *reinterpret_cast(this) == nullptr; } /** RTTI: unique id# for actual runtime data representation **/ virtual typeseq _typeseq() const noexcept = 0; /** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/ diff --git a/include/xo/numeric/detail/RNumeric.hpp b/include/xo/numeric/detail/RNumeric.hpp index 86cac666..35a704ec 100644 --- a/include/xo/numeric/detail/RNumeric.hpp +++ b/include/xo/numeric/detail/RNumeric.hpp @@ -46,6 +46,7 @@ public: ///@{ // explicit injected content + static obj multiply(obj lhs, obj rhs); // builtin methods typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } From 5f2de0ad5a9ad31ebb222fc2f8bd046d14f3d149 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sat, 2 May 2026 13:49:29 -0400 Subject: [PATCH 32/32] xo-gc stack: refactor + streamline. Retiring unused Collector typealiases. Fix #include topology. Fix/improve write barrier setup. --- include/xo/numeric/detail/INumeric_Xfer.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/xo/numeric/detail/INumeric_Xfer.hpp b/include/xo/numeric/detail/INumeric_Xfer.hpp index c9cd2473..bca62e2f 100644 --- a/include/xo/numeric/detail/INumeric_Xfer.hpp +++ b/include/xo/numeric/detail/INumeric_Xfer.hpp @@ -9,10 +9,18 @@ * [iface_facet_any.hpp.j2] * 3. idl for facet methods * [idl/Numeric.json5] + * + * variables: + * {facet_hpp_fname} -> Numeric.hpp + * {impl_hpp_subdir} -> detail + * {facet_ns1} -> xo + * {facet_detail_subdir} -> detail + * {abstract_facet_fname} -> ANumeric.hpp **/ #pragma once +#include "ANumeric.hpp" namespace xo { namespace scm {