From 2d92eec35c5483a1d8c8ac83cb12fad8ebf73f5d Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sat, 6 Jun 2026 22:14:02 -0400 Subject: [PATCH] git subrepo clone git@github.com:Rconybea/xo-numeric.git xo-numeric subrepo: subdir: "xo-numeric" merged: "7750c868" upstream: origin: "git@github.com:Rconybea/xo-numeric.git" branch: "main" commit: "7750c868" git-subrepo: version: "0.4.9" origin: "???" commit: "???" --- xo-numeric/.gitrepo | 12 ++ xo-numeric/CMakeLists.txt | 58 ++++++ xo-numeric/README.md | 1 + xo-numeric/cmake/xo-bootstrap-macros.cmake | 41 ++++ xo-numeric/cmake/xo_numericConfig.cmake.in | 15 ++ xo-numeric/idl/INumeric_DFloat.json5 | 18 ++ xo-numeric/idl/INumeric_DInteger.json5 | 18 ++ xo-numeric/idl/Numeric.json5 | 75 +++++++ .../include/xo/numeric/FloatIntegerOps.hpp | 76 +++++++ xo-numeric/include/xo/numeric/FloatOps.hpp | 47 +++++ xo-numeric/include/xo/numeric/IntegerOps.hpp | 50 +++++ xo-numeric/include/xo/numeric/Numeric.hpp | 22 ++ .../include/xo/numeric/NumericDispatch.hpp | 171 ++++++++++++++++ xo-numeric/include/xo/numeric/NumericOps.hpp | 94 +++++++++ .../include/xo/numeric/NumericPrimitives.hpp | 83 ++++++++ .../include/xo/numeric/SetupNumeric.hpp | 25 +++ .../include/xo/numeric/detail/ANumeric.hpp | 75 +++++++ .../xo/numeric/detail/INumeric_Any.hpp | 87 ++++++++ .../xo/numeric/detail/INumeric_Xfer.hpp | 87 ++++++++ .../include/xo/numeric/detail/RNumeric.hpp | 82 ++++++++ .../xo/numeric/float/INumeric_DFloat.hpp | 56 +++++ .../include/xo/numeric/init_numeric.hpp | 21 ++ .../xo/numeric/integer/INumeric_DInteger.hpp | 56 +++++ xo-numeric/src/numeric/CMakeLists.txt | 25 +++ xo-numeric/src/numeric/FloatIntegerOps.cpp | 174 ++++++++++++++++ xo-numeric/src/numeric/FloatOps.cpp | 96 +++++++++ xo-numeric/src/numeric/INumeric_Any.cpp | 42 ++++ xo-numeric/src/numeric/INumeric_DFloat.cpp | 22 ++ xo-numeric/src/numeric/INumeric_DInteger.cpp | 22 ++ xo-numeric/src/numeric/IntegerOps.cpp | 89 ++++++++ xo-numeric/src/numeric/NumericDispatch.cpp | 192 ++++++++++++++++++ xo-numeric/src/numeric/NumericPrimitives.cpp | 182 +++++++++++++++++ xo-numeric/src/numeric/SetupNumeric.cpp | 162 +++++++++++++++ xo-numeric/src/numeric/init_numeric.cpp | 41 ++++ xo-numeric/utest/CMakeLists.txt | 12 ++ xo-numeric/utest/Numeric.test.cpp | 76 +++++++ xo-numeric/utest/numeric_utest_main.cpp | 24 +++ 37 files changed, 2429 insertions(+) create mode 100644 xo-numeric/.gitrepo create mode 100644 xo-numeric/CMakeLists.txt create mode 100644 xo-numeric/README.md create mode 100644 xo-numeric/cmake/xo-bootstrap-macros.cmake create mode 100644 xo-numeric/cmake/xo_numericConfig.cmake.in create mode 100644 xo-numeric/idl/INumeric_DFloat.json5 create mode 100644 xo-numeric/idl/INumeric_DInteger.json5 create mode 100644 xo-numeric/idl/Numeric.json5 create mode 100644 xo-numeric/include/xo/numeric/FloatIntegerOps.hpp create mode 100644 xo-numeric/include/xo/numeric/FloatOps.hpp create mode 100644 xo-numeric/include/xo/numeric/IntegerOps.hpp create mode 100644 xo-numeric/include/xo/numeric/Numeric.hpp create mode 100644 xo-numeric/include/xo/numeric/NumericDispatch.hpp create mode 100644 xo-numeric/include/xo/numeric/NumericOps.hpp create mode 100644 xo-numeric/include/xo/numeric/NumericPrimitives.hpp create mode 100644 xo-numeric/include/xo/numeric/SetupNumeric.hpp create mode 100644 xo-numeric/include/xo/numeric/detail/ANumeric.hpp create mode 100644 xo-numeric/include/xo/numeric/detail/INumeric_Any.hpp create mode 100644 xo-numeric/include/xo/numeric/detail/INumeric_Xfer.hpp create mode 100644 xo-numeric/include/xo/numeric/detail/RNumeric.hpp create mode 100644 xo-numeric/include/xo/numeric/float/INumeric_DFloat.hpp create mode 100644 xo-numeric/include/xo/numeric/init_numeric.hpp create mode 100644 xo-numeric/include/xo/numeric/integer/INumeric_DInteger.hpp create mode 100644 xo-numeric/src/numeric/CMakeLists.txt create mode 100644 xo-numeric/src/numeric/FloatIntegerOps.cpp create mode 100644 xo-numeric/src/numeric/FloatOps.cpp create mode 100644 xo-numeric/src/numeric/INumeric_Any.cpp create mode 100644 xo-numeric/src/numeric/INumeric_DFloat.cpp create mode 100644 xo-numeric/src/numeric/INumeric_DInteger.cpp create mode 100644 xo-numeric/src/numeric/IntegerOps.cpp create mode 100644 xo-numeric/src/numeric/NumericDispatch.cpp create mode 100644 xo-numeric/src/numeric/NumericPrimitives.cpp create mode 100644 xo-numeric/src/numeric/SetupNumeric.cpp create mode 100644 xo-numeric/src/numeric/init_numeric.cpp create mode 100644 xo-numeric/utest/CMakeLists.txt create mode 100644 xo-numeric/utest/Numeric.test.cpp create mode 100644 xo-numeric/utest/numeric_utest_main.cpp diff --git a/xo-numeric/.gitrepo b/xo-numeric/.gitrepo new file mode 100644 index 00000000..afce2a75 --- /dev/null +++ b/xo-numeric/.gitrepo @@ -0,0 +1,12 @@ +; DO NOT EDIT (unless you know what you are doing) +; +; This subdirectory is a git "subrepo", and this file is maintained by the +; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme +; +[subrepo] + remote = git@github.com:Rconybea/xo-numeric.git + branch = main + commit = 7750c868b6f1fbe7902f27a742596cd4c58b6869 + parent = 378b88d8c4a0ed6e3b68196eed6e4eead7ac4841 + method = merge + cmdver = 0.4.9 diff --git a/xo-numeric/CMakeLists.txt b/xo-numeric/CMakeLists.txt new file mode 100644 index 00000000..fa98c6a4 --- /dev/null +++ b/xo-numeric/CMakeLists.txt @@ -0,0 +1,58 @@ +# 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 + ) + +# ---------------------------------------------------------------- + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-numeric-facetimpl-numeric-float + FACET_PKG xo_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 +# REPR Integer + INPUT idl/INumeric_DInteger.json5 +) + +# ---------------------------------------------------------------- + +xo_add_genfacet_all(xo-numeric-genfacet-all) + +# ---------------------------------------------------------------- + +add_subdirectory(src/numeric) +add_subdirectory(utest) + +# ---------------------------------------------------------------- +# cmake export diff --git a/xo-numeric/README.md b/xo-numeric/README.md new file mode 100644 index 00000000..b4a2c612 --- /dev/null +++ b/xo-numeric/README.md @@ -0,0 +1 @@ +# xo-numeric diff --git a/xo-numeric/cmake/xo-bootstrap-macros.cmake b/xo-numeric/cmake/xo-bootstrap-macros.cmake new file mode 100644 index 00000000..592272c0 --- /dev/null +++ b/xo-numeric/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/xo-numeric/cmake/xo_numericConfig.cmake.in b/xo-numeric/cmake/xo_numericConfig.cmake.in new file mode 100644 index 00000000..a38ab389 --- /dev/null +++ b/xo-numeric/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_procedure2) +find_dependency(subsys) +#find_dependency(indentlog) + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") +check_required_components("@PROJECT_NAME@") diff --git a/xo-numeric/idl/INumeric_DFloat.json5 b/xo-numeric/idl/INumeric_DFloat.json5 new file mode 100644 index 00000000..6b269c6d --- /dev/null +++ b/xo-numeric/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/xo-numeric/idl/INumeric_DInteger.json5 b/xo-numeric/idl/INumeric_DInteger.json5 new file mode 100644 index 00000000..5c478c12 --- /dev/null +++ b/xo-numeric/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/xo-numeric/idl/Numeric.json5 b/xo-numeric/idl/Numeric.json5 new file mode 100644 index 00000000..4ddcc116 --- /dev/null +++ b/xo-numeric/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/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp b/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp new file mode 100644 index 00000000..972e5736 --- /dev/null +++ b/xo-numeric/include/xo/numeric/FloatIntegerOps.hpp @@ -0,0 +1,76 @@ +/** @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); + static obj add(obj rcx, + DFloat * x, DInteger * y); + static obj subtract(obj rcx, + DFloat * x, DInteger * y); + + static obj cmp_equal(obj rcx, + DFloat * x, DInteger * y); + static obj cmp_notequal(obj rcx, + DFloat * x, DInteger * y); + static obj cmp_less(obj rcx, + 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); + }; + + 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); + static obj add(obj rcx, + DInteger * x, DFloat * y); + static obj subtract(obj rcx, + DInteger * x, DFloat * y); + + static obj cmp_equal(obj rcx, + DInteger * x, DFloat * y); + static obj cmp_notequal(obj rcx, + DInteger * x, DFloat * y); + static obj cmp_less(obj rcx, + 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); + }; + + } +} + +/* end FloatIntegerOps.hpp */ diff --git a/xo-numeric/include/xo/numeric/FloatOps.hpp b/xo-numeric/include/xo/numeric/FloatOps.hpp new file mode 100644 index 00000000..f9e6338c --- /dev/null +++ b/xo-numeric/include/xo/numeric/FloatOps.hpp @@ -0,0 +1,47 @@ +/** @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); + static obj add(obj rcx, + DFloat * x, DFloat * y); + static obj subtract(obj rcx, + DFloat * x, DFloat * y); + + static obj cmp_equal(obj rcx, + DFloat * x, DFloat * y); + static obj cmp_notequal(obj rcx, + DFloat * x, DFloat * y); + static obj cmp_less(obj rcx, + 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); + }; + + } +} + +/* end FloatOps.hpp */ diff --git a/xo-numeric/include/xo/numeric/IntegerOps.hpp b/xo-numeric/include/xo/numeric/IntegerOps.hpp new file mode 100644 index 00000000..90eb6e05 --- /dev/null +++ b/xo-numeric/include/xo/numeric/IntegerOps.hpp @@ -0,0 +1,50 @@ +/** @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); + + static obj add(obj rcx, + DInteger * x, DInteger * y); + + static obj subtract(obj rcx, + DInteger * x, DInteger * y); + + static obj cmp_equal(obj rcx, + DInteger * x, DInteger * y); + static obj cmp_notequal(obj rcx, + DInteger * x, DInteger * y); + static obj cmp_less(obj rcx, + 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); + + }; + + } +} + +/* end IntegerOps.hpp */ diff --git a/xo-numeric/include/xo/numeric/Numeric.hpp b/xo-numeric/include/xo/numeric/Numeric.hpp new file mode 100644 index 00000000..54f97420 --- /dev/null +++ b/xo-numeric/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/xo-numeric/include/xo/numeric/NumericDispatch.hpp b/xo-numeric/include/xo/numeric/NumericDispatch.hpp new file mode 100644 index 00000000..bd1f4bf4 --- /dev/null +++ b/xo-numeric/include/xo/numeric/NumericDispatch.hpp @@ -0,0 +1,171 @@ +/** @file NumericDispatch.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#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; + using BinaryOp = AnonymizedNumericOps::BinaryOp; + + /** 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; + } + + /** 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, + obj x, + obj y); + + /** divide w/ runtime polymorphism (double-dispatch) + **/ + static obj divide(obj rcx, + 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); + + /** compare two numeric values for equality (==) **/ + static obj cmp_equal(obj rcx, + obj x, + obj y); + + /** compare two numeric values for inequality (!~=) **/ + static obj cmp_notequal(obj rcx, + obj x, + obj y); + + /** 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); + + /** 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); + + /** 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, + 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 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(), + typeseq::id().seqno()); + + // note: copying op table so they're in proximity + this->dispatch_[key] + = NumericOps::make(mul_fn, + div_fn, + add_fn, + sub_fn, + cmpeq_fn, + cmpne_fn, + cmplt_fn, + cmple_fn, + cmpgt_fn, + cmpge_fn); + } + + private: + /** 2d dispatch for arithmetic **/ + MapType dispatch_; + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end NumericDispatch.hpp */ diff --git a/xo-numeric/include/xo/numeric/NumericOps.hpp b/xo-numeric/include/xo/numeric/NumericOps.hpp new file mode 100644 index 00000000..ea25fb28 --- /dev/null +++ b/xo-numeric/include/xo/numeric/NumericOps.hpp @@ -0,0 +1,94 @@ +/** @file NumericOps.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include +#include +#include +#include + +namespace xo { + namespace scm { + class AnonymizedNumericOps { + public: + using ARuntimeContext = xo::scm::ARuntimeContext; + using AGCObject = xo::mm::AGCObject; + using BinaryOp = obj (*)(obj mm, void * x, void * y); + + public: + /** 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, + BinaryOp add, + BinaryOp subtract, + BinaryOp cmpeq, + 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}, + cmpgt_{cmpgt}, cmpge_{cmpge} {} + + BinaryOp multiply_ = nullptr; + BinaryOp divide_ = nullptr; + BinaryOp add_ = nullptr; + BinaryOp subtract_ = nullptr; + + /** compare numerics (==) **/ + BinaryOp cmpeq_ = nullptr; + /** compare numerics (!=) **/ + BinaryOp cmpne_ = nullptr; + /** compare numerics (<) **/ + BinaryOp cmplt_ = nullptr; + /** compare numerics (<=) **/ + BinaryOp cmple_ = nullptr; + /** compare numerics (>) **/ + BinaryOp cmpgt_ = nullptr; + /** compare numerics (>=) **/ + BinaryOp cmpge_ = nullptr; + }; + + template + class NumericOps { + public: + 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: + static AnonymizedNumericOps make(BinaryOp_Impl multiply, + BinaryOp_Impl divide, + BinaryOp_Impl add, + BinaryOp_Impl subtract, + BinaryOp_Impl cmpeq, + BinaryOp_Impl cmpne, + BinaryOp_Impl cmplt, + BinaryOp_Impl cmple, + BinaryOp_Impl cmpgt, + BinaryOp_Impl cmpge) { + 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(cmple), + reinterpret_cast(cmpgt), + reinterpret_cast(cmpge)); + } + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end NumericOps.hpp */ diff --git a/xo-numeric/include/xo/numeric/NumericPrimitives.hpp b/xo-numeric/include/xo/numeric/NumericPrimitives.hpp new file mode 100644 index 00000000..a1e047f0 --- /dev/null +++ b/xo-numeric/include/xo/numeric/NumericPrimitives.hpp @@ -0,0 +1,83 @@ +/** @file NumericDispatch.hpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#pragma once + +#include + +namespace xo { + namespace scm { + + /** @brief primitives using multidispatch + **/ + class NumericPrimitives { + public: + 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); + + /** 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); + }; + } +} + +/* end NumericDispatch.hpp */ diff --git a/xo-numeric/include/xo/numeric/SetupNumeric.hpp b/xo-numeric/include/xo/numeric/SetupNumeric.hpp new file mode 100644 index 00000000..b6fecd1f --- /dev/null +++ b/xo-numeric/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/xo-numeric/include/xo/numeric/detail/ANumeric.hpp b/xo-numeric/include/xo/numeric/detail/ANumeric.hpp new file mode 100644 index 00000000..7c8e0c99 --- /dev/null +++ b/xo-numeric/include/xo/numeric/detail/ANumeric.hpp @@ -0,0 +1,75 @@ +/** @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 + /** 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 **/ + 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/xo-numeric/include/xo/numeric/detail/INumeric_Any.hpp b/xo-numeric/include/xo/numeric/detail/INumeric_Any.hpp new file mode 100644 index 00000000..0f5a03f2 --- /dev/null +++ b/xo-numeric/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/xo-numeric/include/xo/numeric/detail/INumeric_Xfer.hpp b/xo-numeric/include/xo/numeric/detail/INumeric_Xfer.hpp new file mode 100644 index 00000000..bca62e2f --- /dev/null +++ b/xo-numeric/include/xo/numeric/detail/INumeric_Xfer.hpp @@ -0,0 +1,87 @@ +/** @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] + * + * 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 { + /** @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/xo-numeric/include/xo/numeric/detail/RNumeric.hpp b/xo-numeric/include/xo/numeric/detail/RNumeric.hpp new file mode 100644 index 00000000..35a704ec --- /dev/null +++ b/xo-numeric/include/xo/numeric/detail/RNumeric.hpp @@ -0,0 +1,82 @@ +/** @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 + static obj multiply(obj lhs, obj rhs); + + // 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/xo-numeric/include/xo/numeric/float/INumeric_DFloat.hpp b/xo-numeric/include/xo/numeric/float/INumeric_DFloat.hpp new file mode 100644 index 00000000..8e88438e --- /dev/null +++ b/xo-numeric/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/xo-numeric/include/xo/numeric/init_numeric.hpp b/xo-numeric/include/xo/numeric/init_numeric.hpp new file mode 100644 index 00000000..c3f1cf19 --- /dev/null +++ b/xo-numeric/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/xo-numeric/include/xo/numeric/integer/INumeric_DInteger.hpp b/xo-numeric/include/xo/numeric/integer/INumeric_DInteger.hpp new file mode 100644 index 00000000..ca530949 --- /dev/null +++ b/xo-numeric/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/xo-numeric/src/numeric/CMakeLists.txt b/xo-numeric/src/numeric/CMakeLists.txt new file mode 100644 index 00000000..256f9ad5 --- /dev/null +++ b/xo-numeric/src/numeric/CMakeLists.txt @@ -0,0 +1,25 @@ +# numeric/CMakeLists.txt + +set(SELF_LIB xo_numeric) +set(SELF_SRCS + init_numeric.cpp + SetupNumeric.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/xo-numeric/src/numeric/FloatIntegerOps.cpp b/xo-numeric/src/numeric/FloatIntegerOps.cpp new file mode 100644 index 00000000..fab04cae --- /dev/null +++ b/xo-numeric/src/numeric/FloatIntegerOps.cpp @@ -0,0 +1,174 @@ +/** @file FloatIntegerOps.cp + * + * @author Roland Conybeare, Feb 2206 + **/ + +#include "FloatIntegerOps.hpp" +#include "float/INumeric_DFloat.hpp" +#include + +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()); + } + + 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()); + } + + obj + FloatIntegerOps::cmp_equal(obj rcx, + DFloat * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), + 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())); + } + + obj + FloatIntegerOps::cmp_less(obj rcx, + DFloat * x, DInteger * y) + { + return DBoolean::box(rcx.allocator(), + 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())); + } + + 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) + { + return DBoolean::box(rcx.allocator(), + x->value() >= DFloat::value_type(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()); + } + + 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()); + } + + obj + IntegerFloatOps::cmp_equal(obj rcx, + DInteger * x, DFloat * y) + { + 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()); + } + + obj + IntegerFloatOps::cmp_less(obj rcx, + DInteger * x, DFloat * y) + { + return DBoolean::box(rcx.allocator(), + 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()); + } + + 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) + { + return DBoolean::box(rcx.allocator(), + DFloat::value_type(x->value()) >= y->value()); + } + + } +} + +/* end FloatIntegerOps.cpp */ diff --git a/xo-numeric/src/numeric/FloatOps.cpp b/xo-numeric/src/numeric/FloatOps.cpp new file mode 100644 index 00000000..be522624 --- /dev/null +++ b/xo-numeric/src/numeric/FloatOps.cpp @@ -0,0 +1,96 @@ +/** @file FloatOps.cp + * + * @author Roland Conybeare, Feb 2206 + **/ + +#include "FloatOps.hpp" +#include "float/INumeric_DFloat.hpp" +#include + +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()); + } + + 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()); + } + + obj + FloatOps::cmp_equal(obj rcx, + DFloat * x, DFloat * y) + { + 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()); + } + + obj + FloatOps::cmp_less(obj rcx, + DFloat * x, DFloat * y) + { + 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()); + } + + 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) + { + return DBoolean::box(rcx.allocator(), + x->value() >= y->value()); + } + } +} + +/* end FloatOps.cpp */ diff --git a/xo-numeric/src/numeric/INumeric_Any.cpp b/xo-numeric/src/numeric/INumeric_Any.cpp new file mode 100644 index 00000000..08d27cd0 --- /dev/null +++ b/xo-numeric/src/numeric/INumeric_Any.cpp @@ -0,0 +1,42 @@ +/** @file INumeric_Any.cpp + * + **/ + +#include "detail/INumeric_Any.hpp" +#include +#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 */ diff --git a/xo-numeric/src/numeric/INumeric_DFloat.cpp b/xo-numeric/src/numeric/INumeric_DFloat.cpp new file mode 100644 index 00000000..4024dc04 --- /dev/null +++ b/xo-numeric/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/xo-numeric/src/numeric/INumeric_DInteger.cpp b/xo-numeric/src/numeric/INumeric_DInteger.cpp new file mode 100644 index 00000000..a4ae6a12 --- /dev/null +++ b/xo-numeric/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/xo-numeric/src/numeric/IntegerOps.cpp b/xo-numeric/src/numeric/IntegerOps.cpp new file mode 100644 index 00000000..280e89d3 --- /dev/null +++ b/xo-numeric/src/numeric/IntegerOps.cpp @@ -0,0 +1,89 @@ +/** @file IntegerOps.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "IntegerOps.hpp" +#include "integer/INumeric_DInteger.hpp" +#include + +namespace xo { + using xo::scm::DBoolean; + 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()); + } + + 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()); + } + + obj + IntegerOps::cmp_equal(obj rcx, + DInteger * x, DInteger * y) + { + 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()); + } + + obj + IntegerOps::cmp_less(obj rcx, + DInteger * x, DInteger * y) + { + 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()); + } + + 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) + { + return DBoolean::box(rcx.allocator(), x->value() >= y->value()); + } + + } +} + +/* end IntegerOps.cpp */ diff --git a/xo-numeric/src/numeric/NumericDispatch.cpp b/xo-numeric/src/numeric/NumericDispatch.cpp new file mode 100644 index 00000000..1ebdd414 --- /dev/null +++ b/xo-numeric/src/numeric/NumericDispatch.cpp @@ -0,0 +1,192 @@ +/** @file NumericDispatch.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "NumericDispatch.hpp" +#include +#include +#include + +namespace xo { + using xo::mm::AGCObject; + using xo::facet::TypeRegistry; + + namespace scm { + + void + NumericDispatch::visit_pools(const MemorySizeVisitor & visitor) + { + 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.tseq", x._typeseq()), + xtag("x.type", TypeRegistry::id2name(x._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, + ss.str().c_str()); + } + + return (*target_fn)(rcx, x.data(), y.data()); + } + + obj + NumericDispatch::multiply(obj rcx, + obj x, + obj y) + { + return dispatch(rcx, + "NumericDispatch::multiply", + "incomparable types in x*y", + &AnonymizedNumericOps::multiply_, + x, y); + } + + obj + NumericDispatch::divide(obj rcx, + 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 + = NumericDispatch::instance().dispatch_[key].divide_; + + if (!target_fn) + assert(false); + + return (*target_fn)(rcx, x.data(), y.data()); +#endif + } + + obj + NumericDispatch::add(obj rcx, + obj x, + obj y) + { + return dispatch(rcx, + "NumericDispatch::add", + "incomparable types in x+y", + &AnonymizedNumericOps::add_, + x, y); + } + + obj + NumericDispatch::subtract(obj rcx, + obj x, + obj y) + { + return dispatch(rcx, + "NumericDispatch::subtract", + "incomparable types in x-y", + &AnonymizedNumericOps::subtract_, + x, y); + } + + obj + NumericDispatch::cmp_equal(obj rcx, + obj x, + obj y) + { + return dispatch(rcx, + "NumericDispatch::cmp_equal", + "incomparable types in x==y", + &AnonymizedNumericOps::cmpeq_, + x, y); + + } + + 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); + } + + obj + NumericDispatch::cmp_less(obj rcx, + obj x, + obj y) + { + return dispatch(rcx, + "NumericDispatch::cmp_less", + "incomparable types in x + NumericDispatch::cmp_lessequal(obj rcx, + obj x, + obj y) + { + return dispatch(rcx, + "NumericDispatch::cmp_lessequal", + "incomparable types in x<=y", + &AnonymizedNumericOps::cmple_, + 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_greatequal", + "incomparable types in x>=y", + &AnonymizedNumericOps::cmpge_, + x, y); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end NumericDispatch.cpp **/ diff --git a/xo-numeric/src/numeric/NumericPrimitives.cpp b/xo-numeric/src/numeric/NumericPrimitives.cpp new file mode 100644 index 00000000..9697cc9b --- /dev/null +++ b/xo-numeric/src/numeric/NumericPrimitives.cpp @@ -0,0 +1,182 @@ +/** @file NumericPrimitives.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "NumericPrimitives.hpp" +#include "NumericDispatch.hpp" +#include +#include + +namespace xo { + using xo::mm::AAllocator; + //using xo::mm::AGCObject; + + namespace scm { + + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_multiply_pm(obj mm, + StringTable * stbl) + { + (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, c_multiply_pm_name, pm_ty, + &NumericDispatch::multiply); + } + + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_divide_pm(obj mm, + StringTable * stbl) + { + (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, c_divide_pm_name, pm_ty, + &NumericDispatch::divide); + } + + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_add_pm(obj mm, + StringTable * stbl) + { + (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, c_add_pm_name, pm_ty, + &NumericDispatch::add); + } + + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_subtract_pm(obj mm, + StringTable * stbl) + { + (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, c_sub_pm_name, pm_ty, + &NumericDispatch::subtract); + } + + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmpeq_pm(obj mm, + StringTable * stbl) + { + (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, c_cmpeq_pm_name, pm_ty, + &NumericDispatch::cmp_equal); + } + + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmpne_pm(obj mm, + StringTable * stbl) + { + (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, c_cmpne_pm_name, pm_ty, + &NumericDispatch::cmp_notequal); + } + + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmplt_pm(obj mm, + StringTable * stbl) + { + (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, c_cmplt_pm_name, pm_ty, + &NumericDispatch::cmp_less); + } + + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmple_pm(obj mm, + StringTable * stbl) + { + (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, c_cmple_pm_name, pm_ty, + &NumericDispatch::cmp_lessequal); + } + + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmpgt_pm(obj mm, + StringTable * stbl) + { + (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, c_cmpgt_pm_name, pm_ty, + &NumericDispatch::cmp_greater); + } + + DPrimitive_gco_2_gco_gco * + NumericPrimitives::make_cmpge_pm(obj mm, + StringTable * stbl) + { + (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, c_cmpge_pm_name, pm_ty, + &NumericDispatch::cmp_greatequal); + } + + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end NumericDispatch.cpp */ diff --git a/xo-numeric/src/numeric/SetupNumeric.cpp b/xo-numeric/src/numeric/SetupNumeric.cpp new file mode 100644 index 00000000..58254fc2 --- /dev/null +++ b/xo-numeric/src/numeric/SetupNumeric.cpp @@ -0,0 +1,162 @@ +/** @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; + } + + bool + SetupNumeric::register_primitives(obj rcx, + InstallSink sink, + InstallFlags flags) + { + obj mm = rcx.allocator(); + StringTable * stbl = rcx.stringtable(); + + scope log(XO_DEBUG(false)); + + 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), + flags & InstallFlags::f_essential)); + + return ok; + } + } /*namespace scm*/ +} /*namespace xo*/ + +/* end SetupNumeric.cpp */ diff --git a/xo-numeric/src/numeric/init_numeric.cpp b/xo-numeric/src/numeric/init_numeric.cpp new file mode 100644 index 00000000..86105ec6 --- /dev/null +++ b/xo-numeric/src/numeric/init_numeric.cpp @@ -0,0 +1,41 @@ +/** @file init_numeric.cpp + * + * @author Roland Conybeare, Feb 2026 + **/ + +#include "init_numeric.hpp" +#include "SetupNumeric.hpp" +#include +#include "Subsystem.hpp" + +namespace xo { + using xo::scm::SetupNumeric; + //using xo::scm::numeric_register_primitives; + using xo::scm::PrimitiveRegistry; + + void + InitSubsys::init() + { + SetupNumeric::register_facets(); + + PrimitiveRegistry::instance().register_primitives(&SetupNumeric::register_primitives); + + } + + 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/xo-numeric/utest/CMakeLists.txt b/xo-numeric/utest/CMakeLists.txt new file mode 100644 index 00000000..8b714e4a --- /dev/null +++ b/xo-numeric/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/xo-numeric/utest/Numeric.test.cpp b/xo-numeric/utest/Numeric.test.cpp new file mode 100644 index 00000000..53a44058 --- /dev/null +++ b/xo-numeric/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/xo-numeric/utest/numeric_utest_main.cpp b/xo-numeric/utest/numeric_utest_main.cpp new file mode 100644 index 00000000..96d5d0b6 --- /dev/null +++ b/xo-numeric/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 */