From 07b182d598fd3c41067e3bb989d8016046b13622 Mon Sep 17 00:00:00 2001 From: Jialin Ma Date: Thu, 20 Mar 2025 07:11:45 +0800 Subject: [PATCH 01/11] feat: drop odeintr support --- DESCRIPTION | 5 +- NAMESPACE | 6 +- R/dxdt.R | 216 -------------------------------- R/symbolic_array.R | 7 +- R/symengine.R | 3 +- man/ODESystem.Rd | 91 -------------- man/symengine.Rd | 19 +++ tests/testthat/test-ODESystem.R | 25 ---- vignettes/odesystem.Rmd | 129 ------------------- 9 files changed, 30 insertions(+), 471 deletions(-) delete mode 100644 R/dxdt.R delete mode 100644 man/ODESystem.Rd delete mode 100644 tests/testthat/test-ODESystem.R delete mode 100644 vignettes/odesystem.Rmd diff --git a/DESCRIPTION b/DESCRIPTION index ed50d7c..12fe96c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -17,7 +17,6 @@ Imports: Suggests: crayon, pracma, - odeintr, testthat (>= 2.1.0), knitr, rmarkdown @@ -35,12 +34,11 @@ Encoding: UTF-8 LazyData: true URL: https://github.com/symengine/symengine.R BugReports: https://github.com/symengine/symengine.R/issues -Additional_repositories: https://Marlin-Na.github.io/drat License: GPL (>= 2) Copyright: The R package bundles the 'SymEngine' library source and its subcomponents under 'src/upstream' directory. See file COPYRIGHTS for retained copyright notices as a relicensing and redistribution requirement. -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.2 Collate: 'RcppExports.R' 'basic-getinfo.R' @@ -48,7 +46,6 @@ Collate: 'basic.R' 'codegen.R' 'double_visitor.R' - 'dxdt.R' 'function_symbol.R' 'knitr.R' 'lambdify.R' diff --git a/NAMESPACE b/NAMESPACE index 8413b73..07c9fc5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,8 +1,11 @@ # Generated by roxygen2: do not edit by hand +S3method("[",symArray) +S3method(as.data.frame,symArray) S3method(as.function,BasicOrVecBasic) S3method(as.matrix,DenseMatrix) S3method(cbind,SymEngineDataType) +S3method(print,symArray) S3method(rbind,SymEngineDataType) S3method(rep,Basic) S3method(rep,VecBasic) @@ -15,7 +18,6 @@ export(FunctionSymbol) export(GCD) export(LCM) export(Matrix) -export(ODESystem) export(Real) export(S) export(Symbol) @@ -24,7 +26,6 @@ export(Vector) export(as.language) export(codegen) export(dirichlet_eta) -export(dxdt) export(erf) export(erfc) export(evalf) @@ -57,7 +58,6 @@ exportMethods(choose) exportMethods(det) exportMethods(digamma) exportMethods(factorial) -exportMethods(predict) exportMethods(psigamma) exportMethods(solve) exportMethods(t) diff --git a/R/dxdt.R b/R/dxdt.R deleted file mode 100644 index b20328d..0000000 --- a/R/dxdt.R +++ /dev/null @@ -1,216 +0,0 @@ - -## TODO: handle dynamic parameters, i.e. -## > VdP.sys = ' -## > dxdt[0] = x[1]; -## > dxdt[1] = mu * (1 - x[0] * x[0]) * x[1] - x[0]; -## > ' -## > compile_sys("vpol2", VdP.sys, "mu", method = "bsd") -## > vpol2_set_params(mu = 0.5) - -setClass("DxdtOdeConstructor", slots = c(x="Basic")) -setClass("DxdtOde", slots = c(x = "Basic", rhs = "Basic")) -setClass("ODESystem", slots = c(odesys = "list", cpp_source = "character", - compile_env = "environment")) - -#' Solve System of Ordinary Differential Equations -#' -#' This is a wrapper of the `odeintr` R package using -#' symengine objects to specify the ODE system and C code -#' generation functionality from symengine to generate the -#' C++ source. The `dxdt` function and defined `==` S4 method -#' allow one to intuitively specify the ODE system with symengine -#' objects. The `ODESystem` will generate C++ source -#' and compile on the fly with Rcpp. Then `predict` can be used to get -#' results. -#' -#' @param x A SymEngine Basic object of type Symbol or a R object -#' that will be converted to `Symbol(x)`. -#' @rdname ODESystem -#' @return `dxdt` returns a DxdtOdeConstructor S4 object. -#' @export -#' @md -#' @examples -#' # A differential equation specified with dxdt and == -#' x <- Symbol("x") -#' eq <- dxdt(x) == 1/exp(x) -#' print(eq) -dxdt <- function(x) { - x <- Symbol(x) - new("DxdtOdeConstructor", x = x) -} - -#' @param e1 A DxdtOdeConstructor S4 object which can be returned by `dxdt`. -#' @param e2 A Basic object or an R object that will be converted to `S(e2)`. -#' @return S4 method of `==` for "DxdtOdeConstructor" returns a DxdtOde S4 object. -#' @rdname ODESystem -setMethod("==", signature=c(e1 = "DxdtOdeConstructor", e2 = "ANY"), - function(e1, e2) { - x <- e1@x - rhs <- S(e2) - new("DxdtOde", x = x, rhs = rhs) - } -) - -setMethod("show", signature = c(object = "DxdtOde"), - function(object) { - x <- object@x - rhs <- object@rhs - cat("Ordinary differential equation:\n") - x_str <- as.character(x) - rhs_str <- as.character(rhs) - cat(sprintf("d(%s)/dt == %s\n", x_str, rhs_str)) - } -) - -#' @param odesys,... DxdtOde S4 objects that can be returned with -#' `dxdt(x) == rhs`. Or `odesys` can be a list of DxdtOde S4 objects -#' when there is no dot arguments. -#' @param method,atol,rtol Passed to `odeintr::compile_sys`. -#' @param compile Logical, whether to compile the C++ source. Useful if -#' you only want to obtain the code. -#' @return `ODESystem` returns a ODESystem S4 object. -#' @rdname ODESystem -#' @export -#' @examples -#' \dontrun{ -#' ## Lorenz system -#' use_vars(x, y, z) -#' sigma <- 10 -#' rho <- 28 -#' beta <- 8/3 -#' lorenz_sys <- ODESystem( -#' dxdt(x) == sigma * (y - x), -#' dxdt(y) == (rho - z) * x - y, -#' dxdt(z) == - beta * z + x * y -#' ) -#' res <- predict( -#' lorenz_sys, init = c(x = 1, y = 1, z = 1), duration = 100, step_size = 0.001 -#' ) -#' plot(res[, c(2, 4)], type = 'l', col = "steelblue", main = "Lorenz Attractor") -#' } -ODESystem <- function(odesys, ..., method = "rk5_i", - atol = 1e-06, rtol = 1e-06, compile = TRUE) { - if (!missing(...)) - odesys <- list(odesys, ...) - if (is(odesys, "DxdtOde")) - odesys <- list(odesys) - - ## Some checks - check_odesys <- function(odesys) { - stopifnot(is.list(odesys)) - - for (el in odesys) - stopifnot(is(el, "DxdtOde")) - - rhs_list <- lapply(odesys, function(x) x@rhs) - x_list <- lapply(odesys, function(x) x@x) - - check_symbol <- function(names) { - #if (any(grepl("^_", names))) - # stop(sprintf("variable name [%s] can not start with '_'", - # names[grepl("^_", names)[1]])) - if (any(names == "")) - stop("variable name can not be empty string") - if (any(grepl("(\\[|\\]| )", names))) - stop(sprintf("variable name [%s] can not have space, '[' or ']'", - names[grepl("^_", names)[1]])) - } - check_symbol(unlist(lapply(rhs_list, function(rhs) as.character(free_symbols(rhs))))) - check_symbol(unlist(lapply(x_list, as.character))) - - if (length(unique(Vector(x_list))) != length(x_list)) - stop("lhs variables should be unique") - } - check_odesys(odesys) - - rhs_list <- lapply(odesys, function(x) x@rhs) - x_list <- lapply(odesys, function(x) x@x) - - x_mapping_to <- sprintf("x[%s]", seq(length(x_list)) - 1L) - x_mapping_to <- lapply(x_mapping_to, Symbol) - lhs_mapping_to <- sprintf("dxdt[%s]", seq(length(x_list)) - 1L) - lhs_mapping_to <- lapply(lhs_mapping_to, Symbol) - - rhs_mapping_to <- rhs_list - for (i in seq_along(x_list)) - for (j in seq_along(rhs_mapping_to)) - rhs_mapping_to[[j]] <- subs(rhs_mapping_to[[j]], x_list[[i]], x_mapping_to[[i]]) - - ccode_str <- sprintf("%s = %s", codegen(Vector(lhs_mapping_to), type="ccode"), - codegen(Vector(rhs_mapping_to), type="ccode")) - - compile_sys_env <- new.env() - - if (!requireNamespace("odeintr", quietly = TRUE)) - stop("'odeintr' package needs to be installed for this functionality") - - rcpp_code <- odeintr::compile_sys( - name = "predict", - sys = ccode_str, - pars = NULL, - const = FALSE, - method = method, - sys_dim = length(x_list), - atol = atol, - rtol = rtol, - compile = FALSE, - observer = NULL, - env = compile_sys_env - ) - # Sanity check - stopifnot(length(ls(compile_sys_env, all.names = TRUE)) == 0L) - if (compile) { - res <- Rcpp::sourceCpp( - code = rcpp_code, env = compile_sys_env, verbose = FALSE) - } - - new("ODESystem", odesys = odesys, - cpp_source = rcpp_code, compile_env = compile_sys_env) -} - - -#' @param object A ODESystem S4 object. -#' @param init A numeric vector specifying the initial conditions. It can -#' be named with the variable names or it can be unnamed but in the -#' same of order of equations. -#' @param duration,step_size,start Passed to the function generated by -#' `odeintr::compile_sys`. -#' @return `predict` returns a dataframe. -#' @rdname ODESystem -#' @export -setMethod("predict", c(object = "ODESystem"), - function(object, init, duration, step_size = 1, start = 0) { - x_list <- lapply(object@odesys, function(x) x@x) - x_names <- vapply(x_list, as.character, character(1)) - - stopifnot(length(init) == length(x_list)) - - # Reorder 'init' if it is named - if (!is.null(names(init))) { - matching <- match(x_names, names(init)) - if (anyDuplicated(matching) || any(is.na(matching))) - stop("Invalid names specified 'init'") - init <- init[matching] - } - - ans <- object@compile_env$predict(init, duration, step_size, start) - stopifnot( - identical(names(ans), c("Time", paste0("X", seq_along(x_list)))) - ) - names(ans)[2:length(ans)] <- x_names - ans - } -) - -setMethod("show", c(object = "ODESystem"), - function(object) { - x_list <- lapply(object@odesys, function(x) x@x) - x_names <- vapply(x_list, as.character, character(1)) - rhs_list <- lapply(object@odesys, function(x) x@rhs) - cat(sprintf('%s with variables %s:\n', class(object), - paste(x_names, collapse = ", "))) - for (i in seq_along(x_list)) { - cat(sprintf(" d(%s)/dt = %s\n", x_names[i], as.character(rhs_list[[i]]))) - } - } -) diff --git a/R/symbolic_array.R b/R/symbolic_array.R index 972748f..b5bed14 100644 --- a/R/symbolic_array.R +++ b/R/symbolic_array.R @@ -10,6 +10,7 @@ symArray <- function(...) { ans } +#' @export print.symArray <- function(x, ...) { ## TODO: to improve this... ## maybe we need to define method for format instead? @@ -21,6 +22,7 @@ print.symArray <- function(x, ...) { ## Preserve class attributes for these functions +#' @export `[.symArray` <- function(x,...) { ans <- NextMethod("[") class(ans) <- class(x) @@ -29,5 +31,8 @@ print.symArray <- function(x, ...) { ## So that it can be used in data frame -as.data.frame.symArray <- as.data.frame.vector +#' @export +as.data.frame.symArray <- function(...) { + as.data.frame.vector(...) +} diff --git a/R/symengine.R b/R/symengine.R index d1d3a10..493adf7 100644 --- a/R/symengine.R +++ b/R/symengine.R @@ -69,10 +69,9 @@ #' - `lambertw`, `zeta`, `dirichlet_eta`, `erf`, `erfc` #' - `atan2`, `kronecker_delta`, `lowergamma`, `uppergamma`, `psigamma`, `beta` #' -#' @docType package #' @name symengine #' @md -NULL +"_PACKAGE" #' @import methods #' @importFrom Rcpp cppFunction diff --git a/man/ODESystem.Rd b/man/ODESystem.Rd deleted file mode 100644 index d5ba8a4..0000000 --- a/man/ODESystem.Rd +++ /dev/null @@ -1,91 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/dxdt.R -\name{dxdt} -\alias{dxdt} -\alias{==,DxdtOdeConstructor,ANY-method} -\alias{ODESystem} -\alias{predict,ODESystem-method} -\title{Solve System of Ordinary Differential Equations} -\usage{ -dxdt(x) - -\S4method{==}{DxdtOdeConstructor,ANY}(e1, e2) - -ODESystem( - odesys, - ..., - method = "rk5_i", - atol = 1e-06, - rtol = 1e-06, - compile = TRUE -) - -\S4method{predict}{ODESystem}(object, init, duration, step_size = 1, start = 0) -} -\arguments{ -\item{x}{A SymEngine Basic object of type Symbol or a R object -that will be converted to \code{Symbol(x)}.} - -\item{e1}{A DxdtOdeConstructor S4 object which can be returned by `dxdt`.} - -\item{e2}{A Basic object or an R object that will be converted to `S(e2)`.} - -\item{odesys, ...}{DxdtOde S4 objects that can be returned with -`dxdt(x) == rhs`. Or `odesys` can be a list of DxdtOde S4 objects -when there is no dot arguments.} - -\item{method, atol, rtol}{Passed to `odeintr::compile_sys`.} - -\item{compile}{Logical, whether to compile the C++ source. Useful if -you only want to obtain the code.} - -\item{object}{A ODESystem S4 object.} - -\item{init}{A numeric vector specifying the initial conditions. It can -be named with the variable names or it can be unnamed but in the -same of order of equations.} - -\item{duration, step_size, start}{Passed to the function generated by -`odeintr::compile_sys`.} -} -\value{ -\code{dxdt} returns a DxdtOdeConstructor S4 object. - -S4 method of `==` for "DxdtOdeConstructor" returns a DxdtOde S4 object. - -`ODESystem` returns a ODESystem S4 object. - -`predict` returns a dataframe. -} -\description{ -This is a wrapper of the \code{odeintr} R package using -symengine objects to specify the ODE system and C code -generation functionality from symengine to generate the -C++ source. The \code{dxdt} function and defined \code{==} S4 method -allow one to intuitively specify the ODE system with symengine -objects. The \code{ODESystem} will generate C++ source -and compile on the fly with Rcpp. Then \code{predict} can be used to get -results. -} -\examples{ -# A differential equation specified with dxdt and == -x <- Symbol("x") -eq <- dxdt(x) == 1/exp(x) -print(eq) -\dontrun{ -## Lorenz system -use_vars(x, y, z) -sigma <- 10 -rho <- 28 -beta <- 8/3 -lorenz_sys <- ODESystem( - dxdt(x) == sigma * (y - x), - dxdt(y) == (rho - z) * x - y, - dxdt(z) == - beta * z + x * y -) -res <- predict( - lorenz_sys, init = c(x = 1, y = 1, z = 1), duration = 100, step_size = 0.001 -) -plot(res[, c(2, 4)], type = 'l', col = "steelblue", main = "Lorenz Attractor") -} -} diff --git a/man/symengine.Rd b/man/symengine.Rd index 9f2405f..c0d324a 100644 --- a/man/symengine.Rd +++ b/man/symengine.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/symengine.R \docType{package} \name{symengine} +\alias{symengine-package} \alias{symengine} \title{symengine: R interface to SymEngine C++ library for symbolic computation} \description{ @@ -83,3 +84,21 @@ objects. For example \code{S(~ sin(x) + 1)} and \code{S(quote(sin(x) + 1))}. } } +\seealso{ +Useful links: +\itemize{ + \item \url{https://github.com/symengine/symengine.R} + \item Report bugs at \url{https://github.com/symengine/symengine.R/issues} +} + +} +\author{ +\strong{Maintainer}: Jialin Ma \email{marlin@inventati.org} + +Authors: +\itemize{ + \item Isuru Fernando \email{isuruf@gmail.com} + \item Xin Chen \email{xinchen.tju@gmail.com} +} + +} diff --git a/tests/testthat/test-ODESystem.R b/tests/testthat/test-ODESystem.R deleted file mode 100644 index 2e06b52..0000000 --- a/tests/testthat/test-ODESystem.R +++ /dev/null @@ -1,25 +0,0 @@ - -context("ODESystem") - -test_that("dxdt constructor", { - x <- S("x") - rhs <- x^2L + x + 1L - eq <- dxdt(x) == rhs - expect_true(class(eq) == "DxdtOde") -}) - -x <- S("x") -y <- S("y") -rhs1 <- 1L / (x^2L + y + 1L) -rhs2 <- 1L / (y^2L + 2L*x + 1L) - -test_that("ODESystem and predict works", { - skip_if(!requireNamespace("odeintr", quietly = TRUE)) - eq1 <- dxdt(x) == rhs1 - eq2 <- dxdt(y) == rhs2 - sys <- ODESystem(eq1, eq2) - expect_true(class(sys) == "ODESystem") - res <- predict(sys, init = c(x = 1, y = 1), duration = 10) - expect_true(is.data.frame(res)) - expect_true(identical(names(res), c("Time", "x", "y"))) -}) diff --git a/vignettes/odesystem.Rmd b/vignettes/odesystem.Rmd deleted file mode 100644 index e7422fd..0000000 --- a/vignettes/odesystem.Rmd +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: "Numerical ODE Solver" -output: - rmarkdown::html_vignette: - toc: true -vignette: > - %\VignetteIndexEntry{odesystem} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - - - - -```{r, eval=TRUE, include=FALSE} -if (!all(sapply(c("odeintr"), requireNamespace, quietly = TRUE))) - knitr::opts_chunk$set(eval = FALSE) -``` - -[odeintr](https://github.com/thk686/odeintr) by Timothy H. Keitt is an R package for -integrating differential equations with the -[Boost odeint library](https://headmyshoulder.github.io/odeint-v2/). -It allows specifying the model in C++ code and compiling it on the fly with -Rcpp. - -Here we provide an interface to the `odeintr` package, but - -1. Use an intuitive way to specify the ODE model with symengine objects; -2. Use symengine's code generation functionality to generate the C++ source - and compile with `odeintr`. - -However, the interface is not stable and may subject to change in future. -This mainly serves an example of how to extend symengine and you are welcome -to check out the -[source code](https://github.com/symengine/symengine.R/blob/master/R/dxdt.R). - -```{r} -library(symengine) -``` - -## Define ordinary differential equations with symengine - -A ordinary differential equation could be constructed with `dxdt(x) == rhs` -where `x` and `rhs` will be converted to SymEngine's 'Basic' S4 object. -This works by defining a S4 method of `==` for the return type of `dxdt()`. - -For example - -```{r} -x <- Symbol("x") -a <- 3 -eq <- dxdt(x) == a/(x + 1) -eq -``` - -## Define ODE system - -`ODESystem` will take a list of ordinary differential equations, -generate C++ source code and compile on the fly with Rcpp. -The following is the Lorenz system. - -```{r} -sigma <- 10 -rho <- 28 -beta <- 8/3 -use_vars(x, y, z) -``` - -```{r} -lorenz_sys <- list( - dxdt(x) == sigma * (y - x), - dxdt(y) == (rho - z) * x - y, - dxdt(z) == - beta * z + x * y -) -lorenz_sys <- ODESystem(lorenz_sys, method = "rk5_i") -``` - -The method argument is passed to `odeintr::compile_sys`. - -## Get results - -A S4 method of `predict` is defined to run the model with given -initial conditions, duration and step_size. - -```{r} -res <- predict(lorenz_sys, init = c(x=1, y=1, z=1), - duration = 100, step_size = 0.001, start = 0) -head(res) -``` - -```{r fig.height=5, fig.width=5} -plot(res[, c(2, 4)], type = 'l', col = "steelblue", main = "Lorenz Attractor") -``` - -## Van der Pol Oscillator - -Example of Van der Pol oscillator from `odeintr` package. - -```{r} -use_vars(x, y) -vdp_sys <- ODESystem( - dxdt(x) == y, - dxdt(y) == 2 * (1 - x * x) * y - x, - method = "bsd" # Bulirsch-Stoer -) -res <- predict(vdp_sys, init = rep(1e-4, 2), duration = 100, step_size = 0.01) -``` - -```{r fig.height=5, fig.width=5} -oldpar <- par(mfrow = c(2, 2), mar = rep(0.5, 4), oma = rep(5, 4), xpd = NA) -make.plot <- function(xy, xlab = NA, ylab = NA) - plot(xy, col = "steelblue", lwd = 2, type = "l", - axes = FALSE, xlab = xlab, ylab = ylab) -plot.new() -make.plot(res[, c(3, 1)]); axis(3); axis(4) -make.plot(res[, c(1, 2)], "Time", "X1"); axis(1); axis(2) -make.plot(res[, c(3, 2)], "X2"); axis(1); axis(4) -title(main = "Van der Pol Oscillator", outer = TRUE) -par(oldpar) -``` - - From 0f10c66d5fc6452893e5dd655e4898bf7ded2649 Mon Sep 17 00:00:00 2001 From: Jialin Ma Date: Thu, 20 Mar 2025 07:17:08 +0800 Subject: [PATCH 02/11] feat: bump version to 0.2.7 --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 12fe96c..fb454ed 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: symengine Title: Interface to the 'SymEngine' Library -Version: 0.2.6 +Version: 0.2.7 Authors@R: c(person("Jialin", "Ma", email="marlin@inventati.org", role = c("cre", "aut")), person("Isuru", "Fernando", email="isuruf@gmail.com", role = c("aut")), person("Xin", "Chen", email="xinchen.tju@gmail.com", role = c("aut"))) From abf5983c776f431aa7eb8a41971da79a9a9687e4 Mon Sep 17 00:00:00 2001 From: Jialin Ma Date: Thu, 20 Mar 2025 21:18:12 +0900 Subject: [PATCH 03/11] feat: add cran comments --- tools/cran_comments/cran-comments_0.2.7.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tools/cran_comments/cran-comments_0.2.7.md diff --git a/tools/cran_comments/cran-comments_0.2.7.md b/tools/cran_comments/cran-comments_0.2.7.md new file mode 100644 index 0000000..4696d1f --- /dev/null +++ b/tools/cran_comments/cran-comments_0.2.7.md @@ -0,0 +1,3 @@ + +This version (0.2.7) drops the dependency of odeintr and relevant functionalities, +which should fix the issues in CRAN check results. From ede39bcaffb72aedb6cde76ad099fd1953e8ce4f Mon Sep 17 00:00:00 2001 From: Jialin Ma Date: Thu, 20 Mar 2025 21:19:03 +0900 Subject: [PATCH 04/11] chore: bump version to 0.2.8 --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index fb454ed..27a0751 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: symengine Title: Interface to the 'SymEngine' Library -Version: 0.2.7 +Version: 0.2.8 Authors@R: c(person("Jialin", "Ma", email="marlin@inventati.org", role = c("cre", "aut")), person("Isuru", "Fernando", email="isuruf@gmail.com", role = c("aut")), person("Xin", "Chen", email="xinchen.tju@gmail.com", role = c("aut"))) From 2d9f902982168fb5ec1cd020a9a39aec7e13812a Mon Sep 17 00:00:00 2001 From: Jialin Ma Date: Thu, 20 Mar 2025 21:19:26 +0900 Subject: [PATCH 05/11] feat: replace IS_S4_OBJECT with Rf_isObject and Rf_isS4 --- src/rbinding.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rbinding.cpp b/src/rbinding.cpp index 5a9e688..f429eed 100644 --- a/src/rbinding.cpp +++ b/src/rbinding.cpp @@ -173,7 +173,7 @@ typedef Rcpp::XPtr //// Determine the pointer type by check the tag value inline s4binding_t s4binding_typeof(SEXP x) { - if (IS_S4_OBJECT(x) && R_has_slot(x, Rf_install("ptr"))) { + if (Rf_isObject(x) && Rf_isS4(x) && R_has_slot(x, Rf_install("ptr"))) { SEXP p = R_do_slot(x, Rf_install("ptr")); s4binding_t type = (s4binding_t) RAW(R_ExternalPtrTag(p))[0]; return type; From 3ba2311bb1d84d7921e0e007f3693d73f0af3a3e Mon Sep 17 00:00:00 2001 From: Jialin Ma Date: Thu, 3 Apr 2025 20:59:00 +0800 Subject: [PATCH 06/11] fix: cran warning in mp_class.h --- tools/symengine_patch.diff | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tools/symengine_patch.diff b/tools/symengine_patch.diff index 62d69e2..fabcec2 100644 --- a/tools/symengine_patch.diff +++ b/tools/symengine_patch.diff @@ -31,3 +31,42 @@ set(CMAKE_CXX_FLAGS_RELEASE_INIT "${common} -O3 -funroll-loops") set(CMAKE_CXX_FLAGS_DEBUG_INIT "${common} -g -ggdb") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "PGI") +diff --git src/upstream/symengine/mp_class.h src/upstream/symengine/mp_class.h +index c42d368..12d103e 100644 +--- src/upstream/symengine/mp_class.h ++++ src/upstream/symengine/mp_class.h +@@ -74,12 +74,12 @@ typedef mpq_class rational_class; + inline namespace literals + { + //! Literal for creating multiple precision integers +-inline integer_class operator"" _z(const char *str) ++inline integer_class operator""_z(const char *str) + { + return integer_class(str); + } + +-inline rational_class operator"" _q(const char *str) ++inline rational_class operator""_q(const char *str) + { + return rational_class(integer_class(str)); + } +@@ -1222,6 +1222,9 @@ inline int mp_cmpabs(const integer_class &a, const integer_class &b) + return mpz_cmpabs(get_mpz_t(a), get_mpz_t(b)); + } + ++// from Rmath.h ++extern "C" double unif_rand(void); ++ + class mp_randstate + { + public: +@@ -1241,7 +1244,8 @@ public: + mp_randstate() + { + gmp_randinit_default(_state); +- gmp_randseed_ui(_state, std::rand()); ++ unsigned long int randres = (int)(unif_rand() * (RAND_MAX - 1.0)); ++ gmp_randseed_ui(_state, randres); + } + + ~mp_randstate() From 580dac341d6a695b9a1951d3ba8d3ceafe400676 Mon Sep 17 00:00:00 2001 From: Jialin Ma Date: Thu, 3 Apr 2025 21:27:06 +0800 Subject: [PATCH 07/11] feat: fix cmake_minimum_required version --- tools/symengine_patch.diff | 48 +++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/tools/symengine_patch.diff b/tools/symengine_patch.diff index fabcec2..b401b57 100644 --- a/tools/symengine_patch.diff +++ b/tools/symengine_patch.diff @@ -1,6 +1,14 @@ ---- src/upstream/CMakeLists.txt 2019-11-13 15:14:25.000000000 -0500 -+++ src/upstream/CMakeLists.txt.new 2019-11-19 01:51:57.000000000 -0500 -@@ -535,10 +535,6 @@ +diff --git src/upstream/CMakeLists.txt src/upstream/CMakeLists.txt +index c9f4b8b..43b6394 100644 +--- src/upstream/CMakeLists.txt ++++ src/upstream/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 2.8.12) ++cmake_minimum_required(VERSION 3.5..4.0) + + if (POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) +@@ -539,10 +539,6 @@ if (WITH_OPENMP) set(WITH_SYMENGINE_THREAD_SAFE yes) endif() elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang|GNU) @@ -11,8 +19,23 @@ endif() if (CMAKE_BUILD_TYPE STREQUAL "Debug") ---- src/upstream/cmake/UserOverride.cmake 2019-11-13 15:14:25.000000000 -0500 -+++ src/upstream/cmake/UserOverride.cmake.new 2019-11-19 01:53:01.000000000 -0500 +diff --git src/upstream/cmake/SymEngineConfig.cmake.in src/upstream/cmake/SymEngineConfig.cmake.in +index dbfc80b..8f4ef85 100644 +--- src/upstream/cmake/SymEngineConfig.cmake.in ++++ src/upstream/cmake/SymEngineConfig.cmake.in +@@ -31,7 +31,7 @@ + # target_link_libraries(example ${SYMENGINE_LIBRARIES}) + # + +-cmake_minimum_required(VERSION 2.8.12) ++cmake_minimum_required(VERSION 3.5..4.0) + + if (POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) +diff --git src/upstream/cmake/UserOverride.cmake src/upstream/cmake/UserOverride.cmake +index 523ce49..3e27a3f 100644 +--- src/upstream/cmake/UserOverride.cmake ++++ src/upstream/cmake/UserOverride.cmake @@ -8,7 +8,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") @@ -22,7 +45,7 @@ set(CMAKE_CXX_FLAGS_RELEASE_INIT "${common} -O3 -funroll-loops") set(CMAKE_CXX_FLAGS_DEBUG_INIT "${common} -g -ggdb") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel") -@@ -18,7 +18,7 @@ +@@ -18,7 +18,7 @@ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel") set(CMAKE_CXX_FLAGS_DEBUG_INIT "${common} -g -O0") elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang) # clang @@ -31,6 +54,19 @@ set(CMAKE_CXX_FLAGS_RELEASE_INIT "${common} -O3 -funroll-loops") set(CMAKE_CXX_FLAGS_DEBUG_INIT "${common} -g -ggdb") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "PGI") +diff --git src/upstream/cmake/cotire.cmake src/upstream/cmake/cotire.cmake +index 741d690..e29c180 100644 +--- src/upstream/cmake/cotire.cmake ++++ src/upstream/cmake/cotire.cmake +@@ -37,7 +37,7 @@ set(__COTIRE_INCLUDED TRUE) + if (NOT CMAKE_SCRIPT_MODE_FILE) + cmake_policy(PUSH) + endif() +-cmake_minimum_required(VERSION 2.8.12) ++cmake_minimum_required(VERSION 3.5..4.0) + if (NOT CMAKE_SCRIPT_MODE_FILE) + cmake_policy(POP) + endif() diff --git src/upstream/symengine/mp_class.h src/upstream/symengine/mp_class.h index c42d368..12d103e 100644 --- src/upstream/symengine/mp_class.h From 750f56a70ce136dd67c65a5424e0474594d2cbd9 Mon Sep 17 00:00:00 2001 From: Jialin Ma Date: Thu, 3 Apr 2025 21:49:59 +0800 Subject: [PATCH 08/11] feat: bump version to 0.2.9 --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 27a0751..5e8ec70 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: symengine Title: Interface to the 'SymEngine' Library -Version: 0.2.8 +Version: 0.2.9 Authors@R: c(person("Jialin", "Ma", email="marlin@inventati.org", role = c("cre", "aut")), person("Isuru", "Fernando", email="isuruf@gmail.com", role = c("aut")), person("Xin", "Chen", email="xinchen.tju@gmail.com", role = c("aut"))) From 8445b616efe4c487041b200ebf847cbf813d15be Mon Sep 17 00:00:00 2001 From: Jialin Ma Date: Thu, 3 Apr 2025 21:55:34 +0800 Subject: [PATCH 09/11] feat: add cran comments --- tools/cran_comments/cran-comments_0.2.9.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tools/cran_comments/cran-comments_0.2.9.md diff --git a/tools/cran_comments/cran-comments_0.2.9.md b/tools/cran_comments/cran-comments_0.2.9.md new file mode 100644 index 0000000..534c598 --- /dev/null +++ b/tools/cran_comments/cran-comments_0.2.9.md @@ -0,0 +1,12 @@ + +This version (0.2.9) drops the dependency of odeintr +and relevant functionalities, which should fix the +errors in CRAN check results. + +In addition, it addresses several other issues on CRAN +check: + +1. Replaces the usage of IS_S4_OBJECT and 'rand' in compiled code. +2. Fixes the -Wdeprecated-literal-operator compiler warning +3. Fixes the package build issue when using CMake 4.0 + From 760d4fa7890e73fe229ea9a20e95e6fb19ba53be Mon Sep 17 00:00:00 2001 From: Jialin Ma Date: Fri, 4 Apr 2025 11:41:10 +0800 Subject: [PATCH 10/11] feat: remove assert statements --- tools/symengine_patch.diff | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/tools/symengine_patch.diff b/tools/symengine_patch.diff index b401b57..ecf4eb7 100644 --- a/tools/symengine_patch.diff +++ b/tools/symengine_patch.diff @@ -106,3 +106,51 @@ index c42d368..12d103e 100644 } ~mp_randstate() +diff --git src/upstream/symengine/lambda_double.h src/upstream/symengine/lambda_double.h +index bf6f00d..633605a 100644 +--- src/upstream/symengine/lambda_double.h ++++ src/upstream/symengine/lambda_double.h +@@ -562,7 +562,6 @@ public: + } + void bvisit(const NaN &nan) + { +- assert(&nan == &(*Nan) /* singleton, or do we support NaN quiet/singaling nan with payload? */); + result_ = [](const double * /* x */) { + return std::numeric_limits::signaling_NaN(); + }; +diff --git src/upstream/symengine/parser/parser.tab.cc src/upstream/symengine/parser/parser.tab.cc +index 24628d0..2be7083 100644 +--- src/upstream/symengine/parser/parser.tab.cc ++++ src/upstream/symengine/parser/parser.tab.cc +@@ -1054,7 +1054,6 @@ namespace yy { + case 32: // pwise: PIECEWISE '(' piecewise_list ')' + #line 259 "parser.yy" + { +- assert(yystack_[3].value.as < std::string > () == "Piecewise"); + yylhs.value.as < SymEngine::RCP > () = piecewise(std::move(yystack_[1].value.as < SymEngine::PiecewiseVec > ())); + } + #line 1061 "parser.tab.cc" +diff --git src/upstream/symengine/parser/parser.yy src/upstream/symengine/parser/parser.yy +index 7e106d0..10909bc 100644 +--- src/upstream/symengine/parser/parser.yy ++++ src/upstream/symengine/parser/parser.yy +@@ -256,7 +256,6 @@ piecewise_list: + pwise: + PIECEWISE '(' piecewise_list ')' + { +- assert($1 == "Piecewise"); + $$ = piecewise(std::move($3)); + } + ; +diff --git src/upstream/symengine/utilities/matchpycpp/substitution.h src/upstream/symengine/utilities/matchpycpp/substitution.h +index 056e52a..b6e1760 100644 +--- src/upstream/symengine/utilities/matchpycpp/substitution.h ++++ src/upstream/symengine/utilities/matchpycpp/substitution.h +@@ -50,7 +50,6 @@ substitution_union(const SubstitutionMultiset &subst, + for (const SubstitutionMultiset &other : others) { + for (const pair &p : other) { + int ret = try_add_variable(new_subst, p.first, p.second); +- assert(ret == 0); + } + } + return new_subst; From 6c22371db923fbbb909b34b06fef85486f6b7e64 Mon Sep 17 00:00:00 2001 From: Jialin Ma Date: Fri, 4 Apr 2025 11:42:05 +0800 Subject: [PATCH 11/11] feat: bump version to 0.2.10 --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5e8ec70..154736a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: symengine Title: Interface to the 'SymEngine' Library -Version: 0.2.9 +Version: 0.2.10 Authors@R: c(person("Jialin", "Ma", email="marlin@inventati.org", role = c("cre", "aut")), person("Isuru", "Fernando", email="isuruf@gmail.com", role = c("aut")), person("Xin", "Chen", email="xinchen.tju@gmail.com", role = c("aut")))