diff --git a/Project.toml b/Project.toml index 7a174804..0c8a448e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,8 @@ name = "GTPSA" uuid = "b27dd330-f138-47c5-815b-40db9dd9b6e8" authors = ["Matt Signorelli"] -version = "0.4.0" +version = "0.6" + [deps] GTPSA_jll = "a4739e29-4b97-5c0b-bbcf-46f08034c990" @@ -11,7 +12,7 @@ Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" [compat] -GTPSA_jll = "1.2.1" +GTPSA_jll = "1.3" PrettyTables = "2" SpecialFunctions = "2.3.1" julia = "1.9" diff --git a/README.md b/README.md index 7a367de0..e82daf3a 100644 --- a/README.md +++ b/README.md @@ -4,18 +4,14 @@ [![Build Status](https://github.com/bmad-sim/GTPSA.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/bmad-sim/GTPSA.jl/actions/workflows/CI.yml?query=branch%3Amain) ## Overview - This package provides a full-featured Julia interface to the [Generalised Truncated Power Series Algebra (GTPSA) library](https://mad.web.cern.ch/mad/releases/madng/html/mad_mod_diffalg.html), which computes Taylor expansions, or Truncated Power Series (TPSs) of real and complex multivariable functions to arbitrary orders. -Truncated Power Series Algebra (TPSA) performs forward-mode automatic differentation (AD) similar to the dual-number implementation of `ForwardDiff.jl`. However, instead of nesting derivatives for higher orders, TPSA naturally extends to arbitary orders by directly using the power series expansions. This, paired with a highly optimized monomial indexing function/storage for propagating the partial derivatives, makes `GTPSA.jl` significantly faster for 2nd-order calculations and above (for 1st-order -calculations the performance is similar to `ForwardDiff.jl`). -See the [`benchmark/track.jl`](https://github.com/bmad-sim/GTPSA.jl/blob/main/benchmark/track.jl) example for a speed comparison of `GTPSA.jl` with `ForwardDiff.jl` in calculating the partial derivatives for a system with 58 inputs and 6 outputs. **In this example, GTPSA was nearly x3 faster than ForwardDiff to 2nd order, and x15 faster to 3rd order.** +Truncated Power Series Algebra (TPSA) performs forward-mode automatic differentation (AD) similar to the dual-number implementation of `ForwardDiff.jl`. However, instead of nesting derivatives for higher orders, TPSA naturally extends to arbitary orders by directly using the power series expansions. This, paired with a highly optimized monomial indexing function/storage for propagating the partial derivatives, makes `GTPSA.jl` significantly faster for 2nd-order calculations and above (for 1st-order calculations the performance is similar to `ForwardDiff.jl`).See the [`benchmark/track.jl`](https://github.com/bmad-sim/GTPSA.jl/blob/main/benchmark/track.jl) example for a speed comparison of `GTPSA.jl` with `ForwardDiff.jl` in calculating the partial derivatives for a system with 58 inputs and 6 outputs. **In this example, GTPSA was x3.3 faster than ForwardDiff to 2nd order, and x18.5 faster to 3rd order.** GTPSA provides several advantages over current Julia AD packages: -1. **Speed**: `GTPSA.jl` is significantly faster than `ForwardDiff.jl` for 2nd-order calculations and above, and has similar performance at 1st-order -2. **Custom Orders in Individual Variables**: Other packages use a single maximum order for all variables. With GTPSA, the -maximum order can be set differently for different variables. For example, computing the Taylor expansion of $f(x_1,x_2)$ to 2nd order in $x_1$ and 6th order in $x_2$ is possible +1. **Speed**: `GTPSA.jl` is significantly faster than `ForwardDiff.jl` for 2nd-order calculations and above, and has very similar performance at 1st-order +2. **Custom Orders in Individual Variables**: Other packages use a single maximum order for all variables. With GTPSA, the maximum order can be set differently for individual variables, as well as for a separate part of the monomial. For example, computing the Taylor expansion of $f(x_1,x_2)$ to 2nd order in $x_1$ and 6th order in $x_2$ is possible 3. **Complex Numbers**: GTPSA natively supports complex numbers and allows for mixing of complex and real truncated power series 4. **Distinction Between State Variables and Parameters**: Distinguishing between dependent variables and parameters in the solution of a differential equation expressed as a power series in the dependent variables/parameters can be advantageous in analysis @@ -42,7 +38,7 @@ x = vars() # Manipulate the TPSs as you would any other mathematical variable in Julia f = cos(x[1]) + im*sin(x[2]) -# This creates a new TPS called f +# f is a new ComplexTPS ``` Note that scalars do not need to be defined as TPSs when writing expressions. Running `print(f)` gives the output diff --git a/benchmark/track.jl b/benchmark/track.jl index 9d79c59a..05c3add0 100644 --- a/benchmark/track.jl +++ b/benchmark/track.jl @@ -2,34 +2,35 @@ using GTPSA using ForwardDiff using BenchmarkTools: @btime, @benchmark -# As of 02/19/2024 (Julia v1.10.1) on Mac M2 Ultra: Comparison with GTPSA for 58 inputs and 6 outputs +# As of 05/03/2024, Julia v1.10.2 on Mac M2 Ultra: Comparison with GTPSA for 58 inputs and 6 outputs +# Numbers calculated using BenchmarkTools.@btime # # 3rd Order --------------------------------------------------------- # Using the @FastGTPSA macro: -# GTPSA: 271.137 ms -# ForwardDiff: 4.004 s +# GTPSA: 227.111 ms +# ForwardDiff: 4.212 s # # Without the @FastGTPSA macro (including ForwardDiff as control): -# GTPSA: 415.567 ms -# ForwardDiff: 3.916 s +# GTPSA: 371.465 ms +# ForwardDiff: 4.096 s # # 2nd Order --------------------------------------------------------- # Using the @FastGTPSA macro: -# GTPSA: 8.599 ms -# ForwardDiff: 23.984 ms +# GTPSA: 7.024 ms +# ForwardDiff: 23.417 ms # # Without the @FastGTPSA macro (including ForwardDiff as control): -# GTPSA: 17.141 ms -# ForwardDiff: 23.391 ms +# GTPSA: 15.594 ms +# ForwardDiff: 23.318 ms # # 1st Order --------------------------------------------------------- # Using the @FastGTPSA macro: -# GTPSA: 327.458 μs -# ForwardDiff: 189.417 μs +# GTPSA: 280.542 μs +# ForwardDiff: 188.792 μs # # Without the @FastGTPSA macro (including ForwardDiff as control): -# GTPSA: 707.916 μs -# ForwardDiff: 161.833 μs +# GTPSA: 697.625 μs +# ForwardDiff: 161.125 μs # # Note that @FastGTPSA is transparent to all types except TPS/ComplexTPS, so it can be # inserted into functions while still maintaining generic code, as shown here diff --git a/docs/src/devel.md b/docs/src/devel.md index 4f597ba8..085acfb4 100644 --- a/docs/src/devel.md +++ b/docs/src/devel.md @@ -36,334 +36,349 @@ t1_jl = unsafe_load(Base.unsafe_convert(Ptr{Ptr{RTPSA}}, desc.t), 1) ## Monomial ```@docs -GTPSA.mad_mono_str! -GTPSA.mad_mono_prt! -GTPSA.mad_mono_fill! +GTPSA.mad_mono_add! +GTPSA.mad_mono_cat! +GTPSA.mad_mono_cmp GTPSA.mad_mono_copy! -GTPSA.mad_mono_min +GTPSA.mad_mono_eq +GTPSA.mad_mono_eqn +GTPSA.mad_mono_fill! +GTPSA.mad_mono_le +GTPSA.mad_mono_lt GTPSA.mad_mono_max +GTPSA.mad_mono_min GTPSA.mad_mono_ord GTPSA.mad_mono_ordp GTPSA.mad_mono_ordpf -GTPSA.mad_mono_eq -GTPSA.mad_mono_lt -GTPSA.mad_mono_le -GTPSA.mad_mono_cmp +GTPSA.mad_mono_print +GTPSA.mad_mono_prt! GTPSA.mad_mono_rcmp -GTPSA.mad_mono_add! -GTPSA.mad_mono_sub! -GTPSA.mad_mono_cat! GTPSA.mad_mono_rev! -GTPSA.mad_mono_print +GTPSA.mad_mono_str! +GTPSA.mad_mono_sub! ``` ## Desc ```@docs GTPSA.Desc -GTPSA.mad_desc_newv -GTPSA.mad_desc_newvp -GTPSA.mad_desc_newvpo GTPSA.mad_desc_del! GTPSA.mad_desc_getnv! -GTPSA.mad_desc_maxord -GTPSA.mad_desc_maxlen -GTPSA.mad_desc_gtrunc! -GTPSA.mad_desc_isvalids -GTPSA.mad_desc_isvalidm -GTPSA.mad_desc_isvalidsm -GTPSA.mad_desc_idxs GTPSA.mad_desc_idxm +GTPSA.mad_desc_idxs GTPSA.mad_desc_idxsm -GTPSA.mad_desc_nxtbyvar -GTPSA.mad_desc_nxtbyord -GTPSA.mad_desc_mono! GTPSA.mad_desc_info +GTPSA.mad_desc_isvalidm +GTPSA.mad_desc_isvalids +GTPSA.mad_desc_isvalidsm +GTPSA.mad_desc_maxlen +GTPSA.mad_desc_maxord +GTPSA.mad_desc_mono! +GTPSA.mad_desc_newv +GTPSA.mad_desc_newvp +GTPSA.mad_desc_newvpo +GTPSA.mad_desc_nxtbyord +GTPSA.mad_desc_nxtbyvar ``` ## RTPSA ```@docs GTPSA.RTPSA -GTPSA.mad_tpsa_newd -GTPSA.mad_tpsa_new -GTPSA.mad_tpsa_del! -GTPSA.mad_tpsa_desc -GTPSA.mad_tpsa_uid! -GTPSA.mad_tpsa_len -GTPSA.mad_tpsa_nam -GTPSA.mad_tpsa_ord -GTPSA.mad_tpsa_ordv -GTPSA.mad_tpsa_ordn -GTPSA.mad_tpsa_copy! -GTPSA.mad_tpsa_sclord! -GTPSA.mad_tpsa_getord! -GTPSA.mad_tpsa_cutord! -GTPSA.mad_tpsa_maxord! -GTPSA.mad_tpsa_convert! -GTPSA.mad_tpsa_setvar! -GTPSA.mad_tpsa_setval! -GTPSA.mad_tpsa_setnam! -GTPSA.mad_tpsa_clear! -GTPSA.mad_tpsa_isnul -GTPSA.mad_tpsa_mono! -GTPSA.mad_tpsa_idxs -GTPSA.mad_tpsa_idxm -GTPSA.mad_tpsa_idxsm -GTPSA.mad_tpsa_cycle! -GTPSA.mad_tpsa_get0 -GTPSA.mad_tpsa_geti -GTPSA.mad_tpsa_gets -GTPSA.mad_tpsa_getm -GTPSA.mad_tpsa_getsm -GTPSA.mad_tpsa_set0! -GTPSA.mad_tpsa_seti! -GTPSA.mad_tpsa_sets! -GTPSA.mad_tpsa_setm! -GTPSA.mad_tpsa_setsm! -GTPSA.mad_tpsa_getv! -GTPSA.mad_tpsa_setv! -GTPSA.mad_tpsa_equ -GTPSA.mad_tpsa_dif! -GTPSA.mad_tpsa_add! -GTPSA.mad_tpsa_sub! -GTPSA.mad_tpsa_mul! -GTPSA.mad_tpsa_div! -GTPSA.mad_tpsa_pow! -GTPSA.mad_tpsa_powi! -GTPSA.mad_tpsa_pown! -GTPSA.mad_tpsa_nrm GTPSA.mad_tpsa_abs! -GTPSA.mad_tpsa_sqrt! -GTPSA.mad_tpsa_exp! -GTPSA.mad_tpsa_log! -GTPSA.mad_tpsa_sincos! -GTPSA.mad_tpsa_sin! -GTPSA.mad_tpsa_cos! -GTPSA.mad_tpsa_tan! -GTPSA.mad_tpsa_cot! -GTPSA.mad_tpsa_sinc! -GTPSA.mad_tpsa_sincosh! -GTPSA.mad_tpsa_sinh! -GTPSA.mad_tpsa_cosh! -GTPSA.mad_tpsa_tanh! -GTPSA.mad_tpsa_coth! -GTPSA.mad_tpsa_sinhc! -GTPSA.mad_tpsa_asin! +GTPSA.mad_tpsa_acc! GTPSA.mad_tpsa_acos! -GTPSA.mad_tpsa_atan! +GTPSA.mad_tpsa_acosh! GTPSA.mad_tpsa_acot! +GTPSA.mad_tpsa_acoth! +GTPSA.mad_tpsa_add! +GTPSA.mad_tpsa_asin! GTPSA.mad_tpsa_asinc! GTPSA.mad_tpsa_asinh! -GTPSA.mad_tpsa_acosh! -GTPSA.mad_tpsa_atanh! -GTPSA.mad_tpsa_acoth! GTPSA.mad_tpsa_asinhc! -GTPSA.mad_tpsa_erf! -GTPSA.mad_tpsa_erfc! -GTPSA.mad_tpsa_acc! -GTPSA.mad_tpsa_scl! -GTPSA.mad_tpsa_inv! -GTPSA.mad_tpsa_invsqrt! -GTPSA.mad_tpsa_unit! +GTPSA.mad_tpsa_atan! GTPSA.mad_tpsa_atan2! -GTPSA.mad_tpsa_hypot! -GTPSA.mad_tpsa_hypot3! -GTPSA.mad_tpsa_integ! -GTPSA.mad_tpsa_deriv! -GTPSA.mad_tpsa_derivm! -GTPSA.mad_tpsa_poisbra! -GTPSA.mad_tpsa_taylor! +GTPSA.mad_tpsa_atanh! +GTPSA.mad_tpsa_ax2pby2pcz2! GTPSA.mad_tpsa_axpb! GTPSA.mad_tpsa_axpbypc! +GTPSA.mad_tpsa_axpsqrtbpcx2! GTPSA.mad_tpsa_axypb! -GTPSA.mad_tpsa_axypbzpc! GTPSA.mad_tpsa_axypbvwpc! -GTPSA.mad_tpsa_ax2pby2pcz2! -GTPSA.mad_tpsa_axpsqrtbpcx2! -GTPSA.mad_tpsa_logaxpsqrtbpcx2! -GTPSA.mad_tpsa_logxdy! -GTPSA.mad_tpsa_vec2fld! -GTPSA.mad_tpsa_fld2vec! +GTPSA.mad_tpsa_axypbzpc! +GTPSA.mad_tpsa_clear! +GTPSA.mad_tpsa_clrdensity! +GTPSA.mad_tpsa_clrord! +GTPSA.mad_tpsa_compose! +GTPSA.mad_tpsa_convert! +GTPSA.mad_tpsa_copy! +GTPSA.mad_tpsa_cos! +GTPSA.mad_tpsa_cosh! +GTPSA.mad_tpsa_cot! +GTPSA.mad_tpsa_coth! +GTPSA.mad_tpsa_cpyi! +GTPSA.mad_tpsa_cpym! +GTPSA.mad_tpsa_cpys! +GTPSA.mad_tpsa_cpysm! +GTPSA.mad_tpsa_cutord! +GTPSA.mad_tpsa_cycle! +GTPSA.mad_tpsa_debug +GTPSA.mad_tpsa_del! +GTPSA.mad_tpsa_density +GTPSA.mad_tpsa_deriv! +GTPSA.mad_tpsa_derivm! +GTPSA.mad_tpsa_desc +GTPSA.mad_tpsa_dif! +GTPSA.mad_tpsa_div! +GTPSA.mad_tpsa_equ +GTPSA.mad_tpsa_erf! +GTPSA.mad_tpsa_erfc! +GTPSA.mad_tpsa_eval! +GTPSA.mad_tpsa_exp! +GTPSA.mad_tpsa_exppb! GTPSA.mad_tpsa_fgrad! +GTPSA.mad_tpsa_fld2vec! +GTPSA.mad_tpsa_geti +GTPSA.mad_tpsa_getm +GTPSA.mad_tpsa_getord! +GTPSA.mad_tpsa_gets +GTPSA.mad_tpsa_getsm +GTPSA.mad_tpsa_getv! +GTPSA.mad_tpsa_hypot! +GTPSA.mad_tpsa_hypot3! +GTPSA.mad_tpsa_idxm +GTPSA.mad_tpsa_idxs +GTPSA.mad_tpsa_idxsm +GTPSA.mad_tpsa_init! +GTPSA.mad_tpsa_integ! +GTPSA.mad_tpsa_inv! +GTPSA.mad_tpsa_invsqrt! +GTPSA.mad_tpsa_isnul +GTPSA.mad_tpsa_isval +GTPSA.mad_tpsa_isvalid +GTPSA.mad_tpsa_len GTPSA.mad_tpsa_liebra! -GTPSA.mad_tpsa_exppb! +GTPSA.mad_tpsa_log! +GTPSA.mad_tpsa_logaxpsqrtbpcx2! GTPSA.mad_tpsa_logpb! -GTPSA.mad_tpsa_mnrm +GTPSA.mad_tpsa_logxdy! +GTPSA.mad_tpsa_maxord! +GTPSA.mad_tpsa_mconv! GTPSA.mad_tpsa_minv! +GTPSA.mad_tpsa_mnrm +GTPSA.mad_tpsa_mo! +GTPSA.mad_tpsa_mono! +GTPSA.mad_tpsa_mord +GTPSA.mad_tpsa_mul! +GTPSA.mad_tpsa_nam +GTPSA.mad_tpsa_new +GTPSA.mad_tpsa_newd +GTPSA.mad_tpsa_nrm +GTPSA.mad_tpsa_ord +GTPSA.mad_tpsa_ordv GTPSA.mad_tpsa_pminv! -GTPSA.mad_tpsa_compose! -GTPSA.mad_tpsa_translate! -GTPSA.mad_tpsa_eval! -GTPSA.mad_tpsa_mconv! +GTPSA.mad_tpsa_poisbra! +GTPSA.mad_tpsa_pow! +GTPSA.mad_tpsa_powi! +GTPSA.mad_tpsa_pown! GTPSA.mad_tpsa_print +GTPSA.mad_tpsa_prtdensity GTPSA.mad_tpsa_scan -GTPSA.mad_tpsa_scan_hdr GTPSA.mad_tpsa_scan_coef! -GTPSA.mad_tpsa_debug -GTPSA.mad_tpsa_isvalid -GTPSA.mad_tpsa_init! +GTPSA.mad_tpsa_scan_hdr +GTPSA.mad_tpsa_scl! +GTPSA.mad_tpsa_sclord! +GTPSA.mad_tpsa_seti! +GTPSA.mad_tpsa_setm! +GTPSA.mad_tpsa_setprm! +GTPSA.mad_tpsa_sets! +GTPSA.mad_tpsa_setsm! +GTPSA.mad_tpsa_setv! +GTPSA.mad_tpsa_setval! +GTPSA.mad_tpsa_setvar! +GTPSA.mad_tpsa_sin! +GTPSA.mad_tpsa_sinc! +GTPSA.mad_tpsa_sincos! +GTPSA.mad_tpsa_sincosh! +GTPSA.mad_tpsa_sinh! +GTPSA.mad_tpsa_sinhc! +GTPSA.mad_tpsa_sqrt! +GTPSA.mad_tpsa_sub! +GTPSA.mad_tpsa_tan! +GTPSA.mad_tpsa_tanh! +GTPSA.mad_tpsa_taylor! +GTPSA.mad_tpsa_translate! +GTPSA.mad_tpsa_uid! +GTPSA.mad_tpsa_unit! +GTPSA.mad_tpsa_update! +GTPSA.mad_tpsa_vec2fld! ``` # CTPSA ```@docs GTPSA.CTPSA -GTPSA.mad_ctpsa_newd -GTPSA.mad_ctpsa_new -GTPSA.mad_ctpsa_del! -GTPSA.mad_ctpsa_desc -GTPSA.mad_ctpsa_uid! -GTPSA.mad_ctpsa_len -GTPSA.mad_ctpsa_nam -GTPSA.mad_ctpsa_ord -GTPSA.mad_ctpsa_ordv -GTPSA.mad_ctpsa_ordn -GTPSA.mad_ctpsa_copy! -GTPSA.mad_ctpsa_sclord! -GTPSA.mad_ctpsa_getord! -GTPSA.mad_ctpsa_cutord! -GTPSA.mad_ctpsa_maxord -GTPSA.mad_ctpsa_convert! -GTPSA.mad_ctpsa_setvar! -GTPSA.mad_ctpsa_setvar_r! -GTPSA.mad_ctpsa_setval! -GTPSA.mad_ctpsa_setval_r! -GTPSA.mad_ctpsa_setnam! -GTPSA.mad_ctpsa_clear! -GTPSA.mad_ctpsa_isnul -GTPSA.mad_ctpsa_cplx! -GTPSA.mad_ctpsa_real! -GTPSA.mad_ctpsa_imag! +GTPSA.mad_ctpsa_acc! +GTPSA.mad_ctpsa_acc_r! +GTPSA.mad_ctpsa_acos! +GTPSA.mad_ctpsa_acosh! +GTPSA.mad_ctpsa_acot! +GTPSA.mad_ctpsa_acoth! +GTPSA.mad_ctpsa_add! +GTPSA.mad_ctpsa_addt! +GTPSA.mad_ctpsa_asin! +GTPSA.mad_ctpsa_asinc! +GTPSA.mad_ctpsa_asinh! +GTPSA.mad_ctpsa_asinhc! +GTPSA.mad_ctpsa_atan! +GTPSA.mad_ctpsa_atanh! +GTPSA.mad_ctpsa_ax2pby2pcz2! +GTPSA.mad_ctpsa_ax2pby2pcz2_r! +GTPSA.mad_ctpsa_axpb! +GTPSA.mad_ctpsa_axpb_r! +GTPSA.mad_ctpsa_axpbypc! +GTPSA.mad_ctpsa_axpbypc_r! +GTPSA.mad_ctpsa_axpsqrtbpcx2! +GTPSA.mad_ctpsa_axpsqrtbpcx2_r! +GTPSA.mad_ctpsa_axypb! +GTPSA.mad_ctpsa_axypb_r! +GTPSA.mad_ctpsa_axypbvwpc! +GTPSA.mad_ctpsa_axypbvwpc_r! +GTPSA.mad_ctpsa_axypbzpc! +GTPSA.mad_ctpsa_axypbzpc_r! GTPSA.mad_ctpsa_cabs! GTPSA.mad_ctpsa_carg! -GTPSA.mad_ctpsa_unit! -GTPSA.mad_ctpsa_rect! -GTPSA.mad_ctpsa_polar! -GTPSA.mad_ctpsa_mono! -GTPSA.mad_ctpsa_idxs -GTPSA.mad_ctpsa_idxm -GTPSA.mad_ctpsa_idxsm +GTPSA.mad_ctpsa_clear! +GTPSA.mad_ctpsa_clrord! +GTPSA.mad_ctpsa_compose! +GTPSA.mad_ctpsa_conj! +GTPSA.mad_ctpsa_convert! +GTPSA.mad_ctpsa_copy! +GTPSA.mad_ctpsa_cos! +GTPSA.mad_ctpsa_cosh! +GTPSA.mad_ctpsa_cot! +GTPSA.mad_ctpsa_coth! +GTPSA.mad_ctpsa_cplx! +GTPSA.mad_ctpsa_cpyi! +GTPSA.mad_ctpsa_cpym! +GTPSA.mad_ctpsa_cpys! +GTPSA.mad_ctpsa_cpysm! +GTPSA.mad_ctpsa_cutord! GTPSA.mad_ctpsa_cycle! -GTPSA.mad_ctpsa_get0 +GTPSA.mad_ctpsa_debug +GTPSA.mad_ctpsa_del! +GTPSA.mad_ctpsa_density +GTPSA.mad_ctpsa_deriv! +GTPSA.mad_ctpsa_derivm! +GTPSA.mad_ctpsa_desc +GTPSA.mad_ctpsa_dif! +GTPSA.mad_ctpsa_dift! +GTPSA.mad_ctpsa_div! +GTPSA.mad_ctpsa_divt! +GTPSA.mad_ctpsa_equ +GTPSA.mad_ctpsa_equt +GTPSA.mad_ctpsa_erf! +GTPSA.mad_ctpsa_erfc! +GTPSA.mad_ctpsa_eval! +GTPSA.mad_ctpsa_exp! +GTPSA.mad_ctpsa_exppb! +GTPSA.mad_ctpsa_fgrad! +GTPSA.mad_ctpsa_fld2vec! GTPSA.mad_ctpsa_geti -GTPSA.mad_ctpsa_gets -GTPSA.mad_ctpsa_getm -GTPSA.mad_ctpsa_getsm -GTPSA.mad_ctpsa_set0! -GTPSA.mad_ctpsa_seti! -GTPSA.mad_ctpsa_sets! -GTPSA.mad_ctpsa_setm! -GTPSA.mad_ctpsa_setsm! -GTPSA.mad_ctpsa_get0_r! GTPSA.mad_ctpsa_geti_r! -GTPSA.mad_ctpsa_gets_r! +GTPSA.mad_ctpsa_getm GTPSA.mad_ctpsa_getm_r! +GTPSA.mad_ctpsa_getord! +GTPSA.mad_ctpsa_gets +GTPSA.mad_ctpsa_gets_r! +GTPSA.mad_ctpsa_getsm GTPSA.mad_ctpsa_getsm_r! -GTPSA.mad_ctpsa_set0_r! -GTPSA.mad_ctpsa_seti_r! -GTPSA.mad_ctpsa_sets_r! -GTPSA.mad_ctpsa_setm_r! -GTPSA.mad_ctpsa_setsm_r! GTPSA.mad_ctpsa_getv! -GTPSA.mad_ctpsa_setv! -GTPSA.mad_ctpsa_equ -GTPSA.mad_ctpsa_dif! -GTPSA.mad_ctpsa_add! -GTPSA.mad_ctpsa_sub! +GTPSA.mad_ctpsa_hypot! +GTPSA.mad_ctpsa_hypot3! +GTPSA.mad_ctpsa_idxm +GTPSA.mad_ctpsa_idxs +GTPSA.mad_ctpsa_idxsm +GTPSA.mad_ctpsa_imag! +GTPSA.mad_ctpsa_init! +GTPSA.mad_ctpsa_integ! +GTPSA.mad_ctpsa_inv! +GTPSA.mad_ctpsa_inv_r! +GTPSA.mad_ctpsa_invsqrt! +GTPSA.mad_ctpsa_invsqrt_r! +GTPSA.mad_ctpsa_isnul +GTPSA.mad_ctpsa_isval +GTPSA.mad_ctpsa_isvalid +GTPSA.mad_ctpsa_len +GTPSA.mad_ctpsa_liebra! +GTPSA.mad_ctpsa_log! +GTPSA.mad_ctpsa_logaxpsqrtbpcx2! +GTPSA.mad_ctpsa_logaxpsqrtbpcx2_r! +GTPSA.mad_ctpsa_logpb! +GTPSA.mad_ctpsa_logxdy! +GTPSA.mad_ctpsa_maxord +GTPSA.mad_ctpsa_mconv! +GTPSA.mad_ctpsa_minv! +GTPSA.mad_ctpsa_mnrm +GTPSA.mad_ctpsa_mo! +GTPSA.mad_ctpsa_mono! +GTPSA.mad_ctpsa_mord GTPSA.mad_ctpsa_mul! -GTPSA.mad_ctpsa_div! +GTPSA.mad_ctpsa_mult! +GTPSA.mad_ctpsa_nam +GTPSA.mad_ctpsa_new +GTPSA.mad_ctpsa_newd +GTPSA.mad_ctpsa_nrm +GTPSA.mad_ctpsa_ord +GTPSA.mad_ctpsa_ordv +GTPSA.mad_ctpsa_pminv! +GTPSA.mad_ctpsa_poisbra! +GTPSA.mad_ctpsa_poisbrat! +GTPSA.mad_ctpsa_polar! GTPSA.mad_ctpsa_pow! GTPSA.mad_ctpsa_powi! GTPSA.mad_ctpsa_pown! GTPSA.mad_ctpsa_pown_r! -GTPSA.mad_ctpsa_equt -GTPSA.mad_ctpsa_dift! -GTPSA.mad_ctpsa_tdif! -GTPSA.mad_ctpsa_addt! -GTPSA.mad_ctpsa_subt! -GTPSA.mad_ctpsa_tsub! -GTPSA.mad_ctpsa_mult! -GTPSA.mad_ctpsa_divt! -GTPSA.mad_ctpsa_tdiv! GTPSA.mad_ctpsa_powt! -GTPSA.mad_ctpsa_tpow! -GTPSA.mad_ctpsa_nrm -GTPSA.mad_ctpsa_conj! -GTPSA.mad_ctpsa_sqrt! -GTPSA.mad_ctpsa_exp! -GTPSA.mad_ctpsa_log! -GTPSA.mad_ctpsa_sincos! +GTPSA.mad_ctpsa_print +GTPSA.mad_ctpsa_real! +GTPSA.mad_ctpsa_rect! +GTPSA.mad_ctpsa_scan +GTPSA.mad_ctpsa_scan_coef! +GTPSA.mad_ctpsa_scan_hdr +GTPSA.mad_ctpsa_scl! +GTPSA.mad_ctpsa_scl_r! +GTPSA.mad_ctpsa_sclord! +GTPSA.mad_ctpsa_seti! +GTPSA.mad_ctpsa_seti_r! +GTPSA.mad_ctpsa_setm! +GTPSA.mad_ctpsa_setm_r! +GTPSA.mad_ctpsa_setprm! +GTPSA.mad_ctpsa_setprm_r! +GTPSA.mad_ctpsa_sets! +GTPSA.mad_ctpsa_sets_r! +GTPSA.mad_ctpsa_setsm! +GTPSA.mad_ctpsa_setsm_r! +GTPSA.mad_ctpsa_setv! +GTPSA.mad_ctpsa_setval! +GTPSA.mad_ctpsa_setval_r! +GTPSA.mad_ctpsa_setvar! +GTPSA.mad_ctpsa_setvar_r! GTPSA.mad_ctpsa_sin! -GTPSA.mad_ctpsa_cos! -GTPSA.mad_ctpsa_tan! -GTPSA.mad_ctpsa_cot! GTPSA.mad_ctpsa_sinc! +GTPSA.mad_ctpsa_sincos! GTPSA.mad_ctpsa_sincosh! GTPSA.mad_ctpsa_sinh! -GTPSA.mad_ctpsa_cosh! -GTPSA.mad_ctpsa_tanh! -GTPSA.mad_ctpsa_coth! GTPSA.mad_ctpsa_sinhc! -GTPSA.mad_ctpsa_asin! -GTPSA.mad_ctpsa_acos! -GTPSA.mad_ctpsa_atan! -GTPSA.mad_ctpsa_acot! -GTPSA.mad_ctpsa_asinc! -GTPSA.mad_ctpsa_asinh! -GTPSA.mad_ctpsa_acosh! -GTPSA.mad_ctpsa_atanh! -GTPSA.mad_ctpsa_acoth! -GTPSA.mad_ctpsa_asinhc! -GTPSA.mad_ctpsa_erf! -GTPSA.mad_ctpsa_erfc! -GTPSA.mad_ctpsa_acc! -GTPSA.mad_ctpsa_scl! -GTPSA.mad_ctpsa_inv! -GTPSA.mad_ctpsa_invsqrt! -GTPSA.mad_ctpsa_hypot! -GTPSA.mad_ctpsa_hypot3! -GTPSA.mad_ctpsa_integ! -GTPSA.mad_ctpsa_deriv! -GTPSA.mad_ctpsa_derivm! -GTPSA.mad_ctpsa_poisbra! +GTPSA.mad_ctpsa_sqrt! +GTPSA.mad_ctpsa_sub! +GTPSA.mad_ctpsa_subt! +GTPSA.mad_ctpsa_tan! +GTPSA.mad_ctpsa_tanh! GTPSA.mad_ctpsa_taylor! -GTPSA.mad_ctpsa_poisbrat! +GTPSA.mad_ctpsa_tdif! +GTPSA.mad_ctpsa_tdiv! GTPSA.mad_ctpsa_tpoisbra! -GTPSA.mad_ctpsa_acc_r! -GTPSA.mad_ctpsa_scl_r! -GTPSA.mad_ctpsa_inv_r! -GTPSA.mad_ctpsa_invsqrt_r! -GTPSA.mad_ctpsa_axpb! -GTPSA.mad_ctpsa_axpbypc! -GTPSA.mad_ctpsa_axypb! -GTPSA.mad_ctpsa_axypbzpc! -GTPSA.mad_ctpsa_axypbvwpc! -GTPSA.mad_ctpsa_ax2pby2pcz2! -GTPSA.mad_ctpsa_axpsqrtbpcx2! -GTPSA.mad_ctpsa_logaxpsqrtbpcx2! -GTPSA.mad_ctpsa_logxdy! -GTPSA.mad_ctpsa_axpb_r! -GTPSA.mad_ctpsa_axpbypc_r! -GTPSA.mad_ctpsa_axypb_r! -GTPSA.mad_ctpsa_axypbzpc_r! -GTPSA.mad_ctpsa_axypbvwpc_r! -GTPSA.mad_ctpsa_ax2pby2pcz2_r! -GTPSA.mad_ctpsa_axpsqrtbpcx2_r! -GTPSA.mad_ctpsa_logaxpsqrtbpcx2_r! -GTPSA.mad_ctpsa_vec2fld! -GTPSA.mad_ctpsa_fld2vec! -GTPSA.mad_ctpsa_fgrad! -GTPSA.mad_ctpsa_liebra! -GTPSA.mad_ctpsa_exppb! -GTPSA.mad_ctpsa_logpb! -GTPSA.mad_ctpsa_mnrm -GTPSA.mad_ctpsa_minv! -GTPSA.mad_ctpsa_pminv! -GTPSA.mad_ctpsa_compose! +GTPSA.mad_ctpsa_tpow! GTPSA.mad_ctpsa_translate! -GTPSA.mad_ctpsa_eval! -GTPSA.mad_ctpsa_mconv! -GTPSA.mad_ctpsa_print -GTPSA.mad_ctpsa_scan -GTPSA.mad_ctpsa_scan_hdr -GTPSA.mad_ctpsa_scan_coef! -GTPSA.mad_ctpsa_debug -GTPSA.mad_ctpsa_isvalid -GTPSA.mad_ctpsa_init! +GTPSA.mad_ctpsa_tsub! +GTPSA.mad_ctpsa_uid! +GTPSA.mad_ctpsa_unit! +GTPSA.mad_ctpsa_update! +GTPSA.mad_ctpsa_vec2fld! ``` diff --git a/docs/src/index.md b/docs/src/index.md index 372392d2..70aa3629 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -4,15 +4,12 @@ This package provides a full-featured Julia interface to the [Generalised Truncated Power Series Algebra (GTPSA) library](https://mad.web.cern.ch/mad/releases/madng/html/mad_mod_diffalg.html), which computes Taylor expansions, or Truncated Power Series (TPSs) of real and complex multivariable functions to arbitrary orders. -Truncated Power Series Algebra (TPSA) performs forward-mode automatic differentation (AD) similar to the dual-number implementation of `ForwardDiff.jl`. However, instead of nesting derivatives for higher orders, TPSA naturally extends to arbitary orders by directly using the power series expansions. This, paired with a highly optimized monomial indexing function/storage for propagating the partial derivatives, makes `GTPSA.jl` significantly faster for 2nd-order calculations and above (for 1st-order -calculations the performance is similar to `ForwardDiff.jl`). -See the [`benchmark/track.jl`](https://github.com/bmad-sim/GTPSA.jl/blob/main/benchmark/track.jl) example for a speed comparison of `GTPSA.jl` with `ForwardDiff.jl` in calculating the partial derivatives for a system with 58 inputs and 6 outputs. **In this example, GTPSA was nearly x3 faster than ForwardDiff to 2nd order, and x15 faster to 3rd order.** +Truncated Power Series Algebra (TPSA) performs forward-mode automatic differentation (AD) similar to the dual-number implementation of `ForwardDiff.jl`. However, instead of nesting derivatives for higher orders, TPSA naturally extends to arbitary orders by directly using the power series expansions. This, paired with a highly optimized monomial indexing function/storage for propagating the partial derivatives, makes `GTPSA.jl` significantly faster for 2nd-order calculations and above (for 1st-order calculations the performance is similar to `ForwardDiff.jl`).See the [`benchmark/track.jl`](https://github.com/bmad-sim/GTPSA.jl/blob/main/benchmark/track.jl) example for a speed comparison of `GTPSA.jl` with `ForwardDiff.jl` in calculating the partial derivatives for a system with 58 inputs and 6 outputs. **In this example, GTPSA was x3.3 faster than ForwardDiff to 2nd order, and x18.5 faster to 3rd order.** GTPSA provides several advantages over current Julia AD packages: -1. **Speed**: `GTPSA.jl` is significantly faster than `ForwardDiff.jl` for 2nd-order calculations and above, and has similar performance at 1st-order -2. **Custom Orders in Individual Variables**: Other packages use a single maximum order for all variables. With GTPSA, the -maximum order can be set differently for different variables. For example, computing the Taylor expansion of $f(x_1,x_2)$ to 2nd order in $x_1$ and 6th order in $x_2$ is possible +1. **Speed**: `GTPSA.jl` is significantly faster than `ForwardDiff.jl` for 2nd-order calculations and above, and has very similar performance at 1st-order +2. **Custom Orders in Individual Variables**: Other packages use a single maximum order for all variables. With GTPSA, the maximum order can be set differently for individual variables, as well as for a separate part of the monomial. For example, computing the Taylor expansion of $f(x_1,x_2)$ to 2nd order in $x_1$ and 6th order in $x_2$ is possible 3. **Complex Numbers**: GTPSA natively supports complex numbers and allows for mixing of complex and real truncated power series 4. **Distinction Between State Variables and Parameters**: Distinguishing between dependent variables and parameters in the solution of a differential equation expressed as a power series in the dependent variables/parameters can be advantageous in analysis @@ -39,7 +36,7 @@ x = vars() # Manipulate the TPSs as you would any other mathematical variable in Julia f = cos(x[1]) + im*sin(x[2]) -# This creates a new TPS called f +# f is a new ComplexTPS ``` Note that scalars do not need to be defined as TPSs when writing expressions. Running `print(f)` gives the output diff --git a/docs/src/man/a_toc.md b/docs/src/man/a_toc.md index 97ba6a5d..b2706977 100644 --- a/docs/src/man/a_toc.md +++ b/docs/src/man/a_toc.md @@ -9,7 +9,7 @@ 7. **[Monomial Indexing](@ref monoindex)**: Get/set individual monomial coefficients 8. **[`mono`](@ref mono)**: Creates a TPS corresponding to a specific monomial 9. **[Slicing and `par`](@ref slice)**: Indexing a specific polynomial within the TPS -10. **[TPS and Map Methods](@ref tpsmapmethods)**: Integrate, differentiate, poisson bracket, map (partial) inversion, etc. +10. **[TPS Methods](@ref tpsmethods)**: Integrate, differentiate, composition, evaluation, etc. 11. **[`@FastGTPSA`](@ref fastgtpsa)**: Speed up evaluation of expressions containing TPSs, transparent to other types 12. **[I/O](@ref io)**: Reading/writing TPSs 13. **[All Overloaded Functions](@ref all)**: List of all overloaded Base functions and more \ No newline at end of file diff --git a/docs/src/man/g_monoindex.md b/docs/src/man/g_monoindex.md index 8a9d41ac..d079cd7f 100644 --- a/docs/src/man/g_monoindex.md +++ b/docs/src/man/g_monoindex.md @@ -4,9 +4,12 @@ Individual monomial coefficients in a TPS can be get/set with two methods of indexing: **by order**, and **by sparse monomial**. ## By Order -`t[, ..., ,, ..., ]` +``` +t[[, ..., ,, ..., ]] +t[(, ..., ,, ..., )] +``` -A particular monomial can be indexed by specifying the orders of each variable and parameter. For example, for a TPS `t` with variables ``x_1``, ``x_2`` and parameter ``k_1`` the ``x_1^3x_2^1k_1^2`` monomial coefficient is accessed with `t[3,1,2]`. The 0th order part (the *scalar* part) of the TPS is indexed with `t[0,0,0]` or equivalently `t[0]`, as leaving out trailing zeros for unincluded variables/parameters is allowed. +A particular monomial can be indexed by specifying the orders of each variable and parameter. For example, for a TPS `t` with variables ``x_1``, ``x_2`` and parameters ``k_1``, ``k_2``, the ``x_1^3x_2^1k_1^2`` monomial coefficient is accessed with `t[[3,1,2,0]]` or equivalently `t[[3,1,2]]`, as leaving out trailing zeros for unincluded variables/parameters is allowed. A tuple is also allowed instead of a vector for the list of orders. ### Examples ```@repl @@ -15,16 +18,19 @@ d = Descriptor(2, 6, 3, 6); # 2 variables, 3 parameters all to 6th order x = vars(d); k = params(d); f = 5 + sin(x[1])*sin(x[2])*cos(k[1]) -f[3,1,2] # Leave out trailing zeros for unincluded variables/parameters -f[0] # Scalar part -f[1,1,1,1,1] = 123; # Set monomial coefficient +f[[3,1,2]] # Leave out trailing zeros for unincluded variables/parameters +f[[0]] # Scalar part +f[(1,1,1,1,1)] = 123; # Set monomial coefficient print(f) ``` ## By Sparse Monomial -`t[ => , ..., params=[ => , ...]]` +``` +t[[ => , ...], params=[ => , ...]] +t[( => , ...), params=( => , ...)] +``` -In GTPSAs with many variables and parameters, indexing-by-order is inconvenient because each order needs to be included up to the last included variable/parameter with nonzero order. In this case, a particular monomial can be indexed instead by specifying each variable/parameter number and its corresponding order in pairs. For example, for a TPS with variables ``x_1, ..., x_{15}`` and parameters ``k_1, ..., k_{10}``, the ``x_{1}^3x_{15}^1k_{10}^2`` monomial coefficient is accessed with `t[1=>3, 15=>1, params=[10=>2]]`. The scalar part of the TPS cannot be get/set with this method. +In GTPSAs with many variables and parameters, indexing-by-order is inconvenient because each order needs to be included up to the last included variable/parameter with nonzero order. In this case, a particular monomial can be indexed instead by specifying each variable/parameter number and its corresponding order in pairs. For example, for a TPS with variables ``x_1, ..., x_{15}`` and parameters ``k_1, ..., k_{10}``, the ``x_{1}^3x_{15}^1k_{10}^2`` monomial coefficient is accessed with `t[[1=>3, 15=>1], params=[10=>2]]`. The scalar part of the TPS cannot be get/set with this method. A tuple is also allowed instead of a vector for the list of pairs. ### Examples ```@repl @@ -34,11 +40,39 @@ GTPSA.show_sparse = true; # Use sparse output x = vars(d); k = params(d); f = 5 + sin(x[1])*sin(x[15])*cos(k[10]) -f[1=>3, 15=>1, params=[10=>2]] -f[1=>1, 15=>2, params=[10=>3]] = 123; # Set monomial coefficient +f[[1=>3, 15=>1], params=[10=>2]] +f[(1=>1, 15=>2), params=(10=>3,)] = 123; # Set monomial coefficient print(f) ``` +## By Monomial Index +``` +t[idx] +t[param=param_idx] +``` + +*This indexing method is not recommended/requires care when indexing monomials above first order.* Indexes the TPS with all monomials sorted by order. For example, for a TPS with one variable ``x_1`` and one parameter ``k_1`` the ``x_1`` monomial is indexed with `t[1]` and the ``x_1^2`` monomial is indexed with either `t[3]`. The ``k_1`` monomial can be indexed with either `t[2]` or equivalently using the `param` helper kwarg `t[param=1]`, which simply adds the number of variables in the GTPSA to the provided index. Note that above first-order, the `param` kwarg is basically useless. The zeroth order part, or the *scalar* part of the TPS, can be set with `t[0]`. This method requires zero allocations for indexing, unlike the other two. + +### Examples +```@repl +using GTPSA; GTPSA.show_sparse = false; GTPSA.show_header=false; #hide +# Example of indexing by monomial index ----------- +d = Descriptor(2, 10, 1, 10); +t = TPS(use=d); # Create zero TPS based on d + +t[0] = 0; +t[1] = 1; +t[2] = 2; +t[3] = 3; # or t[param=1] = 3 +t[4] = 4; +t[5] = 5; +t[6] = 6; +t[7] = 7; +t[8] = 8; +t[9] = 9; +t[10] = 10; +print(t) +``` diff --git a/docs/src/man/h_mono.md b/docs/src/man/h_mono.md index ea3e1587..74029593 100644 --- a/docs/src/man/h_mono.md +++ b/docs/src/man/h_mono.md @@ -2,34 +2,34 @@ *Creates a TPS corresponding to a specific monomial* ## Syntax ``` -m = mono(var_idx [, use=(descriptor|tps|complextps)]) -m = mono(param=param_idx [, use=(descriptor|tps|complextps)]) - m = mono(orders [, use=(descriptor|tps|complextps)]) m = mono([vars_sparse_mono] [, params=params_sparse_mono] [, use=(descriptor|tps|complextps)]) +m = mono(idx [, use=(descriptor|tps|complextps)]) +m = mono(param=param_idx [, use=(descriptor|tps|complextps)]) + m = complexmono(...) ``` ## Description -#### Index by Variable/Parameter - -`m = mono(var_idx)` creates a `TPS` equal to the variable specified by `var_idx` and the `Descriptor` in `GTPSA.desc_current` +#### Indexing by Order -`m = mono(param=param_idx)` creates a `TPS` equal to the parameter specified by `param_idx` and the `Descriptor` in `GTPSA.desc_current` +`m = mono(orders)` creates a `TPS` equal to the monomial specified by the indexing-by-order vector/tuple `orders` using the `Descriptor` in `GTPSA.desc_current` ------ -#### Indexing by Order +#### Indexing by Sparse Monomial -`m = mono(orders)` creates a `TPS` equal to the monomial specified by the indexing-by-order vector `orders` and the `Descriptor` in `GTPSA.desc_current` +`m = mono(vars_sparse_mono, params=params_sparse_mono)` creates a `TPS` equal to the monomial specified by the indexing-by-sparse monomial vector/tuple `vars_sparse_mono` and `params_sparse_mono` using the `Descriptor` in `GTPSA.desc_current` ------ -#### Indexing by Sparse Monomial +#### Indexing by Monomial Index + +`m = mono(idx)` creates a `TPS` equal to the monomial specified by `idx` and the `Descriptor` in `GTPSA.desc_current` -`m = mono(vars_sparse_mono, params=params_sparse_mono)` creates a `TPS` equal to the monomial specified by the indexing-by-sparse monomial vector `vars_sparse_mono` and `params_sparse_mono` and the `Descriptor` in `GTPSA.desc_current` +`m = mono(param=param_idx)` creates a `TPS` equal to the monomial specified by `param_idx + nv` where `nv` is the number of variables in the GTPSA, using the `Descriptor` in `GTPSA.desc_current` ------ @@ -50,9 +50,9 @@ d1 = Descriptor(3, 15, 2, 15); # 3 vars, 2 params, all to order 15 x1 = mono(1) k1 = mono(param=1) m312 = mono([3,1,2]) -m31221 = mono([3,1,2,2,1]) +m31221 = mono((3,1,2,2,1)) # Tuples allowed for indexing m312 = mono([1=>3, 2=>1, 3=>3]) -m31221 = mono([1=>3, 2=>1, 3=>2], params=[1=>2, 2=>1]) +m31221 = mono((1=>3, 2=>1, 3=>2), params=(1=>2, 2=>1)) ``` ## Documentation diff --git a/docs/src/man/j_slice.md b/docs/src/man/j_slice.md index d0a659f3..81ecf6e7 100644 --- a/docs/src/man/j_slice.md +++ b/docs/src/man/j_slice.md @@ -10,15 +10,22 @@ d = Descriptor(5, 10, 2, 10); x = vars(d); k = params(d); f = 2*x[1]^2*x[3] + 3*x[1]^2*x[2]*x[3]*x[4]^2*x[5]*k[1] + 6*x[3] + 5 -g = f[2,:,1] -h = f[2,:,1,:] +g = f[[2,:,1]] +h = f[[2,:,1,:]] ``` A TPS can also be sliced with indexing by sparse monomial. In this case, if a colon is included anywhere in the sparse monomial variable index, then all orders of all variables and parameters not explicity specified will be included (colon position does not matter in sparse monomial indexing): ```@repl slice -g = f[1=>2, :, 3=>1, 4=>0, 5=>0, params=[1=>0, 2=>0]] -h = f[1=>2, 3=>1, :] # Colon position is irrelevant in slicing with sparse monomial indexing +g = f[[1=>2, :, 3=>1, 4=>0, 5=>0], params=[1=>0, 2=>0]] +h = f[(1=>2, 3=>1, :)] # Colon position is irrelevant in slicing with sparse monomial indexing +``` + +When indexing by monomial index, a colon simply needs to be included after the variable index, or just a colon if a parameter is specified: + +```@repl slice +fx3 = f[3,:] +fk1 = f[:,param=1] ``` ## `par` @@ -30,22 +37,15 @@ h = f[1=>2, 3=>1, :] # Colon position is irrelevant in slicing with sparse mono ### Syntax ``` -f = par(tps, var_idx) -f = par(tps, param=param_idx) - f = par(tps, orders) f = par(tps [, vars_sparse_mono] [, params=params_sparse_mono]) + +f = par(tps, idx) +f = par(tps, param=param_idx) ``` ### Description -#### Index by Variable/Parameter -`f = par(tps, var_idx)` extracts the polynomial from the TPS with a first-order dependence on the specified variable, and removes the variable from the polynomial - -`f = par(tps, param=param_idx)` extracts the polynomial from the TPS with a first-order dependence on the specified parameter, and removes the parameter from the polynomial - ------- - #### Indexing by Order `f = par(tps, orders)` extracts the polynomial from the TPS with the monomial indexed-by-order in `orders`, and removes the variables/parameters included in the indexing from the polynomial @@ -58,6 +58,14 @@ f = par(tps [, vars_sparse_mono] [, params=params_sparse_mono]) `f = par(tps, vars_sparse_mono, params=params_sparse_mono)` extracts the polynomial from the TPS with the monomial indexed-by-sparse monomial in `vars_sparse_mono` and `params_sparse_mono`, and removes the variables and/or parameters included in the indexing from the polynomial +------ + +#### Indexing by Monomial Index +`f = par(tps, idx)` extracts the polynomial from the TPS with a first-order dependence on the specified monomial, and removes the variable from the polynomial + +`f = par(tps, param=param_idx)` extracts the polynomial from the TPS with a first-order dependence on the specified monomial with index `param_idx+nv` where `nv` is the number of variables in the GTPSA, and removes the parameter from the polynomial + + ### Examples ```@repl par diff --git a/docs/src/man/k_methods.md b/docs/src/man/k_methods.md index fd6ed9cd..0979d428 100644 --- a/docs/src/man/k_methods.md +++ b/docs/src/man/k_methods.md @@ -1,18 +1,21 @@ -# [TPS and Map Methods](@id tpsmapmethods) +# [TPS Methods](@id tpsmethods) ```@docs +clearord +clearord! +clear! +complex! +compose! cutord +cutord! deriv +deriv! evaluate -exppb -fgrad -gethamiltonian +evaluate! getord -getvectorfield +getord! integ -lb -logpb -pb -ptinv +integ! scalar translate +translate! ``` \ No newline at end of file diff --git a/docs/src/man/o_all.md b/docs/src/man/o_all.md index d11e520f..04e64adb 100644 --- a/docs/src/man/o_all.md +++ b/docs/src/man/o_all.md @@ -4,18 +4,21 @@ The following functions from Base have been overloaded for operations with `TPS` +, -, *, /, ^, ∘, inv, atan, hypot, abs, sqrt, exp, log, sin, cos, tan, csc, sec, cot, sinc, sinh, cosh, tanh, csch, sech, coth, asin, acos, atan, acsc, asec, acot, asinh, acosh, -atanh, acsch, asech, acoth, zero, one, real, imag, conj, angle, -complex, promote_rule, getindex, setindex!, ==, <, >, <=, >=, -!=, isequal, show +atanh, acsch, asech, acoth, zero, zeros, one, ones, real, imag, +conj, angle, complex, promote_rule, getindex, setindex!, ==, <, +>, <=, >=, !=, isequal, show, copy!, length, lastindex, firstindex, +rand ``` +`zeros` and `ones` are overloaded from Base so that allocated `TPS`/`ComplexTPS`s are placed in each element. If we didn't explicity overload these functions, every element would correspond to the exact same heap-allocated TPS, which is problematic when setting individual monomial coefficients of the same TPS. + `GTPSA.jl` overloads (and exports) the following functions from the corresponding packages: - **`LinearAlgebra`**: `norm` + **`LinearAlgebra`**: `norm`, `mul!` **`SpecialFunctions`**: `erf`, `erfc` -`GTPSA.jl` also provides the following functions NOT included in Base or any of the above packages: +`GTPSA.jl` also provides the following functions NOT included in Base or any of the above packages (and not already documented in [TPS Methods](@ref tpsmethods)): ``` -unit, sinhc, asinc, asinhc, polar, rect +add!, sub!, div!, unit, sinhc, asinc, asinhc, polar, rect ``` If there is a mathematical function in Base which you'd like and is not included in the above list, feel free to submit an [issue](https://github.com/bmad-sim/GTPSA.jl/issues). \ No newline at end of file diff --git a/docs/src/quickstart.md b/docs/src/quickstart.md index f6e5bad0..6c957a0d 100644 --- a/docs/src/quickstart.md +++ b/docs/src/quickstart.md @@ -52,12 +52,13 @@ Another global variable `GTPSA.show_eps` can be set to exclude showing monomials !!! note The value of a partial derivative is equal to the monomial coefficient in the Taylor series multiplied by a constant factor. E.g. for an expansion around zero ``f(x)\approx f(0) + \frac{\partial f}{\partial x}\rvert_0x + \frac{1}{2!}\frac{\partial^2 f}{\partial x^2}\rvert_0 x^2 + ...``, the 2nd order monomial coefficient is ``\frac{1}{2!}\frac{\partial^2 f}{\partial x^2}\rvert_0``. -Individual monomial coefficients in a TPS `t` can be get/set with two methods of indexing: +Individual monomial coefficients in a TPS `t` can be get/set with three methods of indexing: -1. **By Order:** `t[, ..., ]`. For example, for a TPS with variables ``x_1``, ``x_2``, the ``x_1^3x_2^1`` monomial coefficient is accessed with `t[3,1]`. The 0th order part (the *scalar* part) of the TPS is indexed with `t[0,0]` or equivalently `t[0]`, as leaving out trailing zeros for unincluded variables is allowed. -2. **By Sparse Monomial** `t[ => , ...]`. This method of indexing is convenient when a TPS contains many variables and parameters. For example, for a TPS with variables ``x_1,x_2,...x_{100}``, the ``x_{1}^3x_{99}^1`` monomial coefficient is accessed with `t[1=>3, 99=>1]`. The scalar part of the TPS cannot be get/set with this method. +1. **By Order:** `t[[, ..., ]]`. For example, for a TPS with three variables ``x_1``, ``x_2``, and ``x_3``, the ``x_1^3x_2^1`` monomial coefficient is accessed with `t[[3,1,0]]` or equivalently `t[[3,1]]`, as leaving out trailing zeros for unincluded variables is allowed. A tuple is also allowed instead of a vector for the list of orders. +2. **By Sparse Monomial** `t[[ => , ...]]`. This method of indexing is convenient when a TPS contains many variables and parameters. For example, for a TPS with variables ``x_1,x_2,...x_{100}``, the ``x_{1}^3x_{99}^1`` monomial coefficient is accessed with `t[[1=>3, 99=>1]]`. A tuple is also allowed instead of a vector for the list of pairs. +3. **By Monomial Index** `t[idx]`. *This method is not recommended for indexing above first order.* Indexes the TPS with all monomials sorted by order. For example, for a TPS with two variables ``x_1`` and ``x_2``, the ``x_1`` monomial is indexed with `t[1]` and the ``x_1^2`` monomial is indexed with `t[3]`. The zeroth order part, or the *scalar* part of the TPS, can be set with `t[0]`. This method requires zero allocations for indexing, unlike the other two. -These two methods of indexing are best shown with an example: +These three methods of indexing are best shown with an example: ```@example using GTPSA; GTPSA.show_header=false; GTPSA.show_sparse=false;#hide @@ -65,11 +66,11 @@ using GTPSA; GTPSA.show_header=false; GTPSA.show_sparse=false;#hide d = Descriptor(3, 10); t = TPS(use=d); # Create zero TPS based on d -t[0] = 1; -t[1] = 2; -t[0,1] = 3; -t[0,0,1] = 4; -t[2,1,3] = 5; +t[[0]] = 1; +t[[1]] = 2; +t[[0,1]] = 3; +t[(0,0,1)] = 4; # Tuples also allowed +t[(2,1,3)] = 5; print(t) ``` @@ -80,14 +81,34 @@ using GTPSA; GTPSA.show_header=false; GTPSA.show_sparse=false; #hide d = Descriptor(3, 10); t = TPS(use=d); # Create zero TPS based on d -t[1=>1] = 2; -t[2=>1] = 3; -t[3=>1] = 4; -t[1=>2,2=>1,3=>3] = 5; +t[[1=>1]] = 2; +t[[2=>1]] = 3; +t[[3=>1]] = 4; +t[(1=>2,2=>1,3=>3)] = 5; # Tuples also allowed print(t) ``` +```@example +using GTPSA; GTPSA.show_sparse = false; GTPSA.show_header=false; #hide +# Example of indexing by monomial index ----------- +d = Descriptor(3, 10); +t = TPS(use=d); # Create zero TPS based on d + +t[0] = 0; +t[1] = 1; +t[2] = 2; +t[3] = 3; +t[4] = 4; +t[5] = 5; +t[6] = 6; +t[7] = 7; +t[8] = 8; +t[9] = 9; +t[10] = 10; +print(t) +``` + ### Gradients, Jacobians, Hessians The convenience getters `gradient`, `jacobian`, and `hessian` (as well as their corresponding in-place methods `gradient!`, `jacobian!`, and `hessian!`) are also provided for extracting partial derivatives from a TPS/Vector of TPSs. Note that these functions are not actually calculating anything - at this point the TPS should already have been propagated through the system, and these functions are just extracting the corresponding partial derivatives. @@ -119,8 +140,8 @@ d = Descriptor(5, 10); x = vars(d); f = 2*x[1]^2*x[3] + 3*x[1]^2*x[2]*x[3]*x[4]^2*x[5] + 6*x[3] + 5; -g = f[2,:,1]; -h = f[2,:,1,:]; +g = f[[2,:,1]]; +h = f[[2,:,1,:]]; print(f) print(g) @@ -131,8 +152,8 @@ A TPS can also be sliced with indexing by sparse monomial. In this case, if a co ```@example slice # Colon position does not matter in sparse-monomial indexing -g = f[1=>2, :, 3=>1, 4=>0, 5=>0]; -h = f[1=>2, 3=>1, :]; +g = f[[1=>2, :, 3=>1, 4=>0, 5=>0]]; +h = f[[1=>2, 3=>1, :]]; print(g) diff --git a/src/GTPSA.jl b/src/GTPSA.jl index ccd90fd1..8b42d024 100644 --- a/src/GTPSA.jl +++ b/src/GTPSA.jl @@ -40,7 +40,9 @@ import Base: +, asech , acoth , zero , + zeros , one , + ones , real , imag , conj , @@ -57,9 +59,14 @@ import Base: +, >=, !=, isequal, - show - -import LinearAlgebra: norm + show, + copy!, + length, + lastindex, + firstindex, + rand + +import LinearAlgebra: norm, mul! import SpecialFunctions: erf, erfc using GTPSA_jll, Printf, PrettyTables @@ -78,6 +85,12 @@ export norm, polar, rect, + clear!, + complex!, + add!, + sub!, + mul!, + div!, # Monomial as TPS creators: vars, @@ -99,21 +112,14 @@ export # Methods: - evaluate, - compose, - integ, ∫, - deriv, ∂, - getord, - cutord, - pb, - lb, - getvectorfield, - gethamiltonian, - exppb, - logpb, - fgrad, - ptinv, - translate, + evaluate, evaluate!, + compose, compose!, + integ, ∫, integ!, ∫!, + deriv, ∂, deriv!, ∂!, + getord, getord!, + cutord, cutord!, + clearord, clearord!, + translate, translate!, par, scalar, setGTPSA!, @@ -131,798 +137,16 @@ export __t_asech, __t_acoth, __t_real, __t_imag, __t_conj, __t_angle, __t_complex, __t_sinhc, __t_asinc, __t_asinhc, __t_erf, __t_erfc, __t_norm, __t_polar, __t_rect +include("low.jl") # Low level, 1-to-1 Julia-to-C code including C struct definitions +include("descriptor.jl") # Descriptor struct and constructors +include("global.jl") # Global variables +include("tps.jl") # TPS/ComplexTPS structs and constructors +include("utils.jl") # Utility functions including changing Descriptor of TPS +include("ctors.jl") # Convenience constructors (vars, params, mono) +include("getset.jl") # Indexing/slicing TPS, par, convenience getters (gradient, jacobian, hessian) +include("show.jl") # Output +include("operators.jl") # TPS math overloaded operators/functions +include("methods.jl") # Higher-level TPS functions (derivatives, integrals, evaluate, etc) +include("fast_gtpsa.jl") # Everything for the @FastGTPSA macro - -# Low-level functions/structs and constants -const NAMSZ::Int = 16 -include("low_level/mono.jl") -include("low_level/desc.jl") -include("low_level/rtpsa.jl") -include("low_level/ctpsa.jl") - -# Useful type-generic functions: -cycle!(t::Ptr{RTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_::Ref{Cdouble}) = (@inline; mad_tpsa_cycle!(t, i, n, m_, v_)) -cycle!(t::Ptr{CTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_::Ref{ComplexF64}) = (@inline; mad_ctpsa_cycle!(t, i, n, m_, v_)) -idxm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}) = (@inline; mad_tpsa_idxm(t, n, m)) -idxm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}) = (@inline; mad_ctpsa_idxm(t, n, m)) -seti!(t::Ptr{RTPSA}, i::Cint, a::Cdouble, b::Cdouble) = (@inline; mad_tpsa_seti!(t, i, a, b)) -seti!(t::Ptr{CTPSA}, i::Cint, a::ComplexF64, b::ComplexF64) = (@inline; mad_ctpsa_seti!(t, i, a, b)) -setm!(t::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}, a::Cdouble, b::Cdouble) = (@inline; mad_tpsa_setm!(t, n, m, a, b)) -setm!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}, a::ComplexF64, b::ComplexF64) = (@inline; mad_ctpsa_setm!(t, n, m, a, b)) - -const MAD_TPSA::String = :("libgtpsa") -const MAD_TPSA_DEFAULT::Cuchar = 255 -const MAD_TPSA_SAME::Cuchar = 254 -const MAD_DESC_CURR::Ptr{Desc} = C_NULL -const DESC_MAX_TMP::Int = 8 - -# Wrapper struct for Ptr{Desc} -struct Descriptor - desc::Ptr{Desc} - function Descriptor(desc::Ptr{Desc})::Descriptor - d = new(desc) - return d - end -end - -# Global non-constants (types MUST be specified) -desc_current::Descriptor = Descriptor(MAD_DESC_CURR) # Current Descriptor -show_eps::Float64 = 0.0 # Print epsilon -show_sparse::Bool = false # Use sparse monomial print -show_header::Bool = false # Print a header above each TPS - -""" - setGTPSA!(a::AbstractString, val) - -Function to set global variables in GTPSA. Options for `a` are: - -- `desc_current::Descriptor` -- defines the `Descriptor` to use when that information is not explicitly (or implicitly in a TPS copy constructor) available, e.g. when calling `TPS(a)` where `a` is not a TPS. This is set each time a new `Descriptor` is defined -- `show_eps::Float64` -- defines the value below which the absolute value of a monomial coefficient is NOT printed -- `show_sparse::Bool` -- specifies whether the sparse monomial format is used for printing. This is useful for GTPSAs containing a large number of variables and parameters -- `show_header::Bool` -- specifies whether or not to print the GTPSA `Descriptor` information above each TPS output -""" -function setGTPSA!(a::AbstractString, val) - a == "desc_current" && (return (GTPSA.desc_current = val)) - a == "show_eps" && (return (GTPSA.show_eps = val)) - a == "show_sparse" && (return (GTPSA.show_sparse = val)) - a == "show_header" && (return (GTPSA.show_header = val)) - error("Global variable \"$(a)\" does not exist!") -end - -""" - getGTPSA(a::AbstractString) - -Function to get global variables in GTPSA. Options for `a` are: - -- `desc_current::Descriptor` -- defines the `Descriptor` to use when that information is not explicitly (or implicitly in a TPS copy constructor) available, e.g. when calling `TPS(a)` where `a` is not a TPS. This is set each time a new `Descriptor` is defined -- `show_eps::Float64` -- defines the value below which the absolute value of a monomial coefficient is NOT printed -- `show_sparse::Bool` -- specifies whether the sparse monomial format is used for printing. This is useful for GTPSAs containing a large number of variables and parameters -- `show_header::Bool` -- specifies whether or not to print the GTPSA `Descriptor` information above each TPS output -""" -function getGTPSA(a::AbstractString) - a == "desc_current" && (return GTPSA.desc_current) - a == "show_eps" && (return GTPSA.show_eps) - a == "show_sparse" && (return GTPSA.show_sparse) - a == "show_header" && (return GTPSA.show_header) - error("Global variable \"$(a)\" does not exist!") -end - -# Descriptor outer constructors -""" - Descriptor(nv::Integer, mo::Integer)::Descriptor - -Creates a TPSA `Descriptor` with `nv` variables, and a maximum truncation order `mo`. - -### Input -- `nv` -- Number of variables in the TPSA -- `mo` -- Maximum truncation order of the TPSA -""" -function Descriptor(nv::Integer, mo::Integer)::Descriptor - d = Descriptor(mad_desc_newv(convert(Cint, nv), convert(Cuchar, mo))) - GTPSA.desc_current = d - return d -end - -""" - Descriptor(vos::Vector{<:Integer}, mo::Integer)::Descriptor - -Creates a TPSA `Descriptor` with `length(vos)` variables with individual truncation -orders specified in the Vector `vos`, and a maximum truncation order `mo` for the TPSA. - -### Input -- `vos` -- `Vector` of the individual truncation orders of each variable -- `mo` -- Maximum truncation order of the TPSA, <= sum(vos) -""" -function Descriptor(vos::Vector{<:Integer}, mo::Integer)::Descriptor - all(vos .<= mo) == true || error("Atleast one variable truncation order is > the maximum truncation order!") - mo <= sum(vos) || (@info "Maximum order too high: setting maximum order = sum($vos) = $(sum(vos))"; mo = sum(vos)) - nv = length(vos) - np = 0 - po = 0 - no = vos - d = Descriptor(mad_desc_newvpo(convert(Cint, nv), convert(Cuchar, mo), convert(Cint, np), convert(Cuchar, po), convert(Vector{Cuchar}, no))) - GTPSA.desc_current = d - return d -end - -""" - Descriptor(nv::Integer, mo::Integer, np::Integer, po::Integer)::Descriptor - -Creates a TPSA `Descriptor` with `nv` variables and `np` parameters. The maximum -truncation order is `mo` (including the parameters), and the truncation order for -the parameters part of a monomial is `po`. - -### Input -- `nv` -- Number of variables in the TPSA -- `mo` -- Maximum truncation order of the TPSA including variables and parameters -- `np` -- Number of parameters in the TPSA -- `po` -- Truncation order of the parameters part of a monomial -""" -function Descriptor(nv::Integer, mo::Integer, np::Integer, po::Integer)::Descriptor - d = Descriptor(mad_desc_newvp(convert(Cint, nv), convert(Cuchar, mo), convert(Cint, np), convert(Cuchar, po))) - GTPSA.desc_current = d - return d -end - - -""" - Descriptor(vos::Vector{<:Integer}, mo::Integer, pos::Vector{<:Integer}, po::Integer)::Descriptor - -Creates a TPSA `Descriptor` with `length(vos)` variables with individual truncation -orders specified in `vos`, and `length(pos)` parameters with individual truncation -orders specified in `pos`. The maximum truncation order including both variables and -parameters is `mo`, and the truncation order for just the parameters part of the is `po`. - -### Input -- `vos` -- `Vector` of the individual truncation orders of each variable -- `mo` -- Maximum truncation order of the TPSA including variables and parameters -- `pos` -- `Vector` of the individual truncation orders of each parameter -- `po` -- Truncation order of the parameters part of a monomial -""" -function Descriptor(vos::Vector{<:Integer}, mo::Integer, pos::Vector{<:Integer}, po::Integer)::Descriptor - nv = length(vos) - np = length(pos) - no = vcat(vos,pos) - d = Descriptor(mad_desc_newvpo(convert(Cint, nv), convert(Cuchar, mo), convert(Cint, np), convert(Cuchar, po), convert(Vector{Cuchar}, no))) - GTPSA.desc_current = d - return d -end - -# Wrapper struct for Ptr{RTPSA} -mutable struct TPS <: Real - tpsa::Ptr{RTPSA} - function TPS(t1::Ptr{RTPSA})::TPS - t = new(t1) - f(x) = mad_tpsa_del!(x.tpsa) - finalizer(f,t) - return t - end -end - -# Wrapper struct for Ptr{CTPSA} -mutable struct ComplexTPS <: Number - tpsa::Ptr{CTPSA} - function ComplexTPS(ct1::Ptr{CTPSA})::ComplexTPS - ct = new(ct1) - f(x) = mad_ctpsa_del!(x.tpsa) - finalizer(f,ct) - return ct - end -end - -""" - TPS(ta::Union{Real,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::TPS - -Constructor to create a new `TPS` equal to the real value `ta`. If `ta` is a `TPS`, this -is equivalent to a copy constructor, with the result by default having the same `Descriptor` as `ta`. -If `ta` is not a `TPS`, then the `Descriptor` used will by default be `GTPSA.desc_current`. The `Descriptor` -for the constructed `TPS` can be set using `use`. If a `TPS` or `ComplexTPS` is passed to `use`, -the `Descriptor` for that TPS will be used. - -The constructor can also be used to create a copy of a `TPS` under one `Descriptor` to instead -have a different `Descriptor`. In this case, invalid monomials under the new `Descriptor` are removed. - -### Input -- `ta` -- Any `Real` -- `use` -- (Optional) specify which `Descriptor` to use, default is `nothing` which uses the `Descriptor` for `ta` if `ta isa TPS`, else uses `GTPSA.desc_current` - -### Output -- `ret` -- New `TPS` equal to `ta` with removal of invalid monomials if `ta` is a `TPS` and a new `Descriptor` is specified -""" -function TPS(ta::Union{Real,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::TPS - return low_TPS(ta, use) -end - -# --- Blank TPS --- -function low_TPS(ta::Nothing, use::Descriptor) - return TPS(mad_tpsa_newd(use.desc, MAD_TPSA_DEFAULT)) -end - -function low_TPS(ta::Nothing, use::Union{TPS,ComplexTPS}) - return TPS(mad_tpsa_new(Base.unsafe_convert(Ptr{RTPSA}, use.tpsa), MAD_TPSA_SAME)) -end - -function low_TPS(ta::Nothing, use::Nothing) - return TPS(mad_tpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) -end - -# --- Copy ctor --- -function low_TPS(t1::TPS, use::Nothing) - t = TPS(mad_tpsa_new(t1.tpsa, MAD_TPSA_SAME)) - mad_tpsa_copy!(t1.tpsa, t.tpsa) - return t -end - -# --- Change descriptor --- -function low_TPS(t1::TPS, use::Descriptor) - return change(t1, use) -end - -function low_TPS(t1::TPS, use::Union{TPS,ComplexTPS}) - return change(t1, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa).d))) -end - -# --- promote real to TPS --- -function low_TPS(a::Real, use::Nothing) - t = TPS(mad_tpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) - mad_tpsa_set0!(t.tpsa, convert(Float64, 0), convert(Float64,a)) - return t -end - -function low_TPS(a::Real, use::Union{TPS,ComplexTPS}) - t = TPS(mad_tpsa_new(Base.unsafe_convert(Ptr{RTPSA}, use.tpsa), MAD_TPSA_SAME)) - mad_tpsa_set0!(t.tpsa, 0.0, convert(Float64,a)) - return t -end - -function low_TPS(a::Real, use::Descriptor) - t = TPS(mad_tpsa_newd(use.desc, MAD_TPSA_DEFAULT)) - mad_tpsa_set0!(t.tpsa, 0.0, convert(Float64,a)) - return t -end - -# ----------------------- -""" - ComplexTPS(cta::Union{Number,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::ComplexTPS - -Constructor to create a new `ComplexTPS` equal to the number `cta`. If `cta` is a `ComplexTPS` (or `TPS`), this -is equivalent to a copy constructor, with the result by default having the same `Descriptor` as `cta`. If `cta` -is not a `TPS` or`ComplexTPS`, then the `Descriptor` used will by default be `GTPSA.desc_current`. The `Descriptor` -for the constructed `ComplexTPS` can be set using `use`. If a `TPS` or `ComplexTPS` is passed to `use`, -the `Descriptor` for that TPS will be used. - -The constructor can also be used to create a copy of a `ComplexTPS` under one `Descriptor` to instead -have a different `Descriptor`. In this case, invalid monomials under the new `Descriptor` are removed. - -### Input -- `cta` -- Any `Number` -- `use` -- (Optional) specify which `Descriptor` to use, default is `nothing` which uses the `Descriptor` for `cta` if `cta <: Union{TPS,ComplexTPS}`, else uses `GTPSA.desc_current` - -### Output -- `ret` -- New `ComplexTPS` equal to `cta` with removal of invalid monomials if `cta` is a `TPS`/`ComplexTPS` and a new `Descriptor` is specified -""" -function ComplexTPS(cta::Union{Number,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::ComplexTPS - return low_ComplexTPS(cta, use) -end - -# For some reason I need to explicitly define this: -ComplexTPS(t::ComplexTPS; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing) = low_ComplexTPS(t,use) - -# --- Blank ComplexTPS --- -function low_ComplexTPS(cta::Nothing, use::Descriptor) - return ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) -end - -function low_ComplexTPS(cta::Nothing, use::Union{TPS,ComplexTPS}) - return ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) -end - -function low_ComplexTPS(cta::Nothing, use::Nothing) - return ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) -end - -# --- Copy ctor --- -function low_ComplexTPS(ct1::ComplexTPS, use::Nothing) - ct = ComplexTPS(mad_ctpsa_new(ct1.tpsa, MAD_TPSA_SAME)) - mad_ctpsa_copy!(ct1.tpsa, ct.tpsa) - return ct -end - -function low_ComplexTPS(t1::TPS, use::Nothing) - ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ct.tpsa) - return ct -end - -# --- Change descriptor --- -function low_ComplexTPS(t1::Union{TPS,ComplexTPS}, use::Descriptor) - return change(t1, use) -end - -function low_ComplexTPS(t1::Union{TPS,ComplexTPS}, use::Union{TPS,ComplexTPS}) - return change(t1, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa).d))) -end - -# --- promote number to ComplexTPS --- -function low_ComplexTPS(a::Union{Real,Complex}, use::Nothing) - ct = ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64,a)) - return ct -end - -function low_ComplexTPS(a::Union{Real,Complex}, use::Union{TPS,ComplexTPS}) - ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64,a)) - return ct -end - -function low_ComplexTPS(a::Union{Real,Complex}, use::Descriptor) - ct = ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64,a)) - return ct -end - -# ----------------------- - -# Special real argument ctors -function ComplexTPS(ta::Real, tb::Real; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::ComplexTPS - low_ComplexTPS(ta, tb, use) -end - -function low_ComplexTPS(t1::TPS, t2::TPS, use::Nothing) - ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_cplx!(t1.tpsa, t2.tpsa, ct.tpsa) - return ct -end - -function low_ComplexTPS(t1::TPS, a::Real, use::Nothing) - ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ct.tpsa) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, complex(0,a))) - return ct -end - -function low_ComplexTPS(a::Real, t1::TPS, use::Nothing) - ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_cplx!(Base.unsafe_convert(Ptr{RTPSA}, C_NULL), t1.tpsa, ct.tpsa) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) - return ct -end - -function low_ComplexTPS(a::Real, b::Real, use::Nothing) - ct = ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) - return ct -end - -function low_ComplexTPS(a::Real, b::Real, use::Descriptor) - ct = ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) - return ct -end - -function low_ComplexTPS(a::Real, b::Real, use::Union{TPS,ComplexTPS}) - ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) - return ct -end - -function low_ComplexTPS(ta::TPS, tb::TPS, use::Descriptor) - ct = change(ta, use, type=ComplexTPS) - change!(ct, tb, 1, im) - return ct -end - -function low_ComplexTPS(ta::TPS, b::Real, use::Descriptor) - ct = change(ta, use, type=ComplexTPS) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, complex(0,b))) - return ct -end - -function low_ComplexTPS(a::Real, tb::TPS, use::Descriptor) - ct = change(tb, use, type=ComplexTPS, scl2=im) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) - return ct -end - -function low_ComplexTPS(ta::TPS, tb::TPS, use::Union{TPS,ComplexTPS}) - return low_ComplexTPS(ta, tb, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa)))) -end - -function low_ComplexTPS(ta::TPS, b::Real, use::Union{TPS,ComplexTPS}) - return low_ComplexTPS(ta, b, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa)))) -end - -function low_ComplexTPS(a::Real, tb::TPS, use::Union{TPS,ComplexTPS}) - return low_ComplexTPS(a, tb, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa)))) -end - -# --- Variable/parameter generators --- - -""" - vars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} - -Returns `TPS`s corresponding to the variables for the `Descriptor` specified by `use`. -Default value is `GTPSA.desc_current`. - -### Input -- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` - -### Output -- `x` -- `Vector` containing unit `TPS`s corresponding to each variable -""" -function vars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} - t1 = TPS(use=use) - desc = unsafe_load(mad_tpsa_desc(t1.tpsa)) - nv = desc.nv - if nv < 1 - return TPS[] - end - x = Vector{TPS}(undef, nv) - t1[1] = 1.0 - x[1] = t1 - for i=2:nv - t = TPS(use=use) - mad_tpsa_seti!(t.tpsa, Cint(i), 0.0, 1.0) - x[i] = t - end - return x -end - -""" - params(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} - -Returns `TPS`s corresponding to the parameters for the `Descriptor` specified by `use`. -Default value is `GTPSA.desc_current`. - -### Input -- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` - -### Output -- `k` -- `Vector` containing unit `TPS`s corresponding to each parameter -""" -function params(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} - t1 = TPS(use=use) - desc = unsafe_load(mad_tpsa_desc(t1.tpsa)) - nv = desc.nv - np = desc.np - if np < 1 - return TPS[] - end - k = Vector{TPS}(undef, np) - mad_tpsa_seti!(t1.tpsa, Cint(nv+1), 0.0, 1.0) - k[1] = t1 - for i=nv+2:nv+np - t = TPS(use=use) - mad_tpsa_seti!(t.tpsa, Cint(i), 0.0, 1.0) - k[i-nv] = t - end - return k -end - - -""" - complexvars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{ComplexTPS} - -Returns `ComplexTPS`s corresponding to the variables for the `Descriptor` specified by `use`. -Default value is `GTPSA.desc_current`. - -### Input -- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` - -### Output -- `x` -- `Vector` containing unit `ComplexTPS`s corresponding to each variable -""" -function complexvars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{ComplexTPS} - ct1 = ComplexTPS(use=use) - desc = unsafe_load(mad_ctpsa_desc(ct1.tpsa)) - nv = desc.nv - if nv < 1 - return ComplexTPS[] - end - x = Vector{ComplexTPS}(undef, nv) - ct1[1] = 1.0 - x[1] = ct1 - for i=2:nv - ct = ComplexTPS(use=use) - mad_ctpsa_seti!(ct.tpsa, Cint(i), ComplexF64(0.0), ComplexF64(1.0)) - x[i] = ct - end - return x -end - -""" - complexparams(d::Descriptor=GTPSA.desc_current)::Vector{ComplexTPS} - -Returns `ComplexTPS`s corresponding to the parameters for the `Descriptor` specified by `use`. -Default value is `GTPSA.desc_current`. - -### Input -- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` - -### Output -- `k` -- `Vector` containing unit `ComplexTPS`s corresponding to each parameter -""" -function complexparams(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{ComplexTPS} - ct1 = ComplexTPS(use=use) - desc = unsafe_load(mad_ctpsa_desc(ct1.tpsa)) - nv = desc.nv - np = desc.np - if np < 1 - return ComplexTPS[] - end - k = Vector{ComplexTPS}(undef, np) - mad_ctpsa_seti!(ct1.tpsa, Cint(nv+1), ComplexF64(0.0), ComplexF64(1.0)) - k[1] = ct1 - for i=nv+2:nv+np - ct = ComplexTPS(use=use) - mad_ctpsa_seti!(ct.tpsa, Cint(i), ComplexF64(0.0), ComplexF64(1.0)) - k[i-nv] = ct - end - return k -end - -""" - mono(v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing, use::Descriptor=GTPSA.desc_current)::TPS - -Returns a `TPS` corresponding to a specific monomial, specified using the variable/parameter index, or -monomial indexing-by-order OR monomial indexing-by-sparse monomial. - -### Input -- `v` -- An integer (for variable index), an array of orders for each variable (for indexing-by-order), or an array of pairs (sparse monomial) -- `param` -- (Keyword argument, optional) An integer for the parameter index -- `params` -- (Keyword argument, optional) An array of pairs for sparse-monomial indexing -- `use` -- (Keyword argument, optional) The descriptor to use to generate the monomial. Default is most recently-defined. - -# Examples: Variable/Parameter Index: -```julia-repl -julia> d = Descriptor(3,10,2,10); - -julia> mono(1) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 1 0 0 0 0 - - -julia> mono(2, use=d) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 0 1 0 0 0 - - -julia> mono(param=2) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 0 0 0 0 1 -``` - -# Examples: Monomial Index-by-Order -```julia-repl -julia> mono([1]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 1 0 0 0 0 - - -julia> mono([0,1]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 0 1 0 0 0 - - -julia> mono([0,0,0,0,1], use=d) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 0 0 0 0 1 - - -julia> mono([1,0,0,0,1]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 2 1 0 0 0 1 -``` - -# Examples: Monomial Index-by-Sparse Monomial -```julia-repl -julia> mono([1=>1]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 1 0 0 0 0 - - -julia> mono([2=>1]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 0 1 0 0 0 - - -julia> mono([1=>1], params=[2=>1], use=d) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 2 1 0 0 0 1 -``` -""" -function mono(v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing, use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::TPS - return low_mono(TPS, use, v, param, params) -end - -function complexmono(v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing, use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::ComplexTPS - return low_mono(ComplexTPS, use, v, param, params) -end - -# Variable/parameter: -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Integer, param::Nothing, params::Nothing)::T - t = T(use=d) - seti!(t.tpsa, Cint(v), convert(numtype(T), 0.0), convert(numtype(T), 1.0)) - return t -end - -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Nothing, param::Integer, params::Nothing)::T - t = T(use=d) - desc = unsafe_load(mad_tpsa_desc(t.tpsa)) - nv = desc.nv # TOTAL NUMBER OF VARS!!!! - seti!(t.tpsa, Cint(param) + nv, convert(numtype(T), 0.0), convert(numtype(T), 1.0)) - return t -end - -# Default to scalar value if nothing passed -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Nothing)::T - t = T(use=d) - t[0] = 1.0 - return t -end - -# Monomial by order: -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Vector{<:Integer}, param::Nothing, params::Nothing)::T - t = T(use=d) - t[v...] = 1.0 - return t -end - -# Monomial by sparse monomial: -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Vector{<:Pair{<:Integer,<:Integer}}, param::Nothing, params::Vector{<:Pair{<:Integer,<:Integer}})::T - t = T(use=d) - t[v..., params=params] = 1.0 - return t -end - -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Vector{<:Pair{<:Integer,<:Integer}}, param::Nothing, params::Nothing)::T - t = T(use=d) - # Need to create array of orders with length nv + np - t[v...] = 1.0 - return t -end - -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Vector{<:Pair{<:Integer,<:Integer}})::T - t = T(use=d) - t[params=params] = 1.0 - return t -end - -# Throw error if no above use cases satisfied: -function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v, param, params) - error("Invalid monomial specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") -end - -# Function to convert var=>ord, params=(param=>ord,) to low level sparse monomial format (varidx1, ord1, varidx2, ord2, paramidx, ordp1,...) -function pairs_to_sm(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}; params::Vector{<:Pair{<:Integer,<:Integer}}=Pair{Int,Int}[])::Tuple{Vector{Cint}, Cint} - # WE MUST Order THE VARIABLES !!! - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)) - nv = desc.nv # TOTAL NUMBER OF VARS!!!!!! - numv = Cint(length(vars)) - nump = Cint(length(params)) - imin = min(minimum(x->x.first, vars,init=typemax(Int)), minimum(x->x.first+nv, params,init=typemax(Int))) - imax = max(maximum(x->x.first, vars,init=0), maximum(x->x.first+nv, params,init=0)) - len = imax-imin+1 - sm = zeros(Cint, 2*len) - sm[1:2:end] = imin:imax - for i=1:numv - sm[2*(vars[i].first-imin+1)] = convert(Cint, vars[i].second) - end - for i=1:nump - sm[2*(params[i].first+nv-imin+1)] = convert(Cint, params[i].second) - end - - return sm, 2*len -end - -# Function to convert var=>ord, params=(param=>ord,) to monomial format (byte array of orders) -function pairs_to_m(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}; params::Vector{<:Pair{<:Integer,<:Integer}}=Pair{Int,Int}[],zero_mono=true)::Tuple{Vector{UInt8}, Cint} - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)) - nv = desc.nv - n = Cint(0) - if isempty(params) - n = Cint(maximum(map(x->x.first, vars))) - else - n = Cint(maximum(map(x->x.first, params))) + nv - end - if zero_mono - ords = zeros(Cuchar, n) - else - ords = ones(Cuchar, n).*0xff - end - for var in vars - ords[var.first] = convert(Cuchar, var.second) - end - for param in params - ords[nv + param.first] = convert(Cuchar, param.second) - end - return ords, n -end - -# Generic function to make new copy of TPS with different descriptor -function change(t1::Union{TPS,ComplexTPS}, newd::Descriptor; type::Type=typeof(t1), scl2::Number=1) - # Quick check if actually changing - if Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d) == newd.desc - return type(t1) - end - - # THE NUMBER OF VARIABLES and PARAMETERS MUST AGREE!!! - unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)).nv == unsafe_load(newd.desc).nv || error("Number of variables in GTPSAs do not agree!") - unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)).np == unsafe_load(newd.desc).np || error("Number of parameters in GTPSAs do not agree!") - - t = type(use=newd) - change!(t, t1, 0, scl2) - return t -end - -function change!(t::Union{TPS,ComplexTPS},t1::Union{TPS,ComplexTPS}, scl1::Number=0, scl2::Number=1) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) - nv = desc.nv - np = desc.np - coef = Ref{numtype(t1)}() - mono = Vector{Cuchar}(undef, np+nv) - idx = cycle!(t1.tpsa, Cint(-1), np+nv, mono, coef) - while idx >= 0 - # if valid monomial in new descriptor: - if convert(Bool, mad_desc_isvalidm(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d), np+nv, mono)) - setm!(t.tpsa, np+nv, mono, convert(numtype(t), scl1), convert(numtype(t), scl2*coef[])) # set new tpsa - end - idx = cycle!(t1.tpsa, idx, np+nv, mono, coef) - end -end - -include("getset.jl") -include("show.jl") -include("operators.jl") -include("methods.jl") -include("fast_gtpsa.jl") - -# Prevent undefined behavior -# Until AbstractComplex is implemented, I make the ctor return error because this should never happen -# asumming I wrapped enough -#= -Complex(t1::TPS) = complex(t1) -Complex(t1::TPS, t2::TPS) = complex(t1, t2) -Complex(t1::TPS, a::Real) = complex(t1, a) -Complex(a::Real, t1::TPS) = complex(a, t1) -Complex{TPS}(t1::TPS) = complex(t1) -Complex{TPS}(t1::TPS, t2::TPS) = complex(t1, t2) -Complex{TPS}(t1::TPS, a::Real) = complex(t1, a) -Complex{TPS}(a::Real, t1::TPS) = complex(a, t1)=# -Complex(t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex(t1::TPS, t2::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex(t1::TPS, a::Real) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex(a::Real, t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex{TPS}(t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex{TPS}(t1::TPS, t2::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex{TPS}(t1::TPS, a::Real) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") -Complex{TPS}(a::Real, t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") - - -promote_rule(::Type{TPS}, ::Union{Type{<:AbstractFloat}, Type{<:Integer}, Type{<:Rational}, Type{<:AbstractIrrational}}) = TPS -promote_rule(::Type{ComplexTPS}, ::Union{Type{Complex{<:Real}},Type{<:AbstractFloat}, Type{<:Integer}, Type{<:Rational}, Type{<:AbstractIrrational}}) = ComplexTPS -promote_rule(::Type{TPS}, ::Union{Type{ComplexTPS}, Type{Complex{<:Real}}}) = ComplexTPS - -# Handle bool which is special for some reason -+(t::TPS, z::Complex{Bool}) = t + Complex{Int}(z) -+(z::Complex{Bool}, t::TPS) = Complex{Int}(z) + t --(t::TPS, z::Complex{Bool}) = t - Complex{Int}(z) --(z::Complex{Bool}, t::TPS) = Complex{Int}(z) - t -*(t::TPS, z::Complex{Bool}) = t * Complex{Int}(z) -*(z::Complex{Bool}, t::TPS) = Complex{Int}(z) * t -/(t::TPS, z::Complex{Bool}) = t / Complex{Int}(z) -/(z::Complex{Bool}, t::TPS) = Complex{Int}(z) / t -^(t::TPS, z::Complex{Bool}) = t ^ Complex{Int}(z) -^(z::Complex{Bool}, t::TPS) = Complex{Int}(z) ^ t end diff --git a/src/ctors.jl b/src/ctors.jl new file mode 100644 index 00000000..c067d1bc --- /dev/null +++ b/src/ctors.jl @@ -0,0 +1,241 @@ + + +# --- Variable/parameter generators --- + +""" + vars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} + +Returns `TPS`s corresponding to the variables for the `Descriptor` specified by `use`. +Default value is `GTPSA.desc_current`. + +### Input +- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` + +### Output +- `x` -- `Vector` containing unit `TPS`s corresponding to each variable +""" +function vars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} + nv = numvars(use) + x = Vector{TPS}(undef, nv) + for i=1:nv + t = TPS(use=use) + t[i] = 1.0 + x[i] = t + end + return x +end + +""" + params(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} + +Returns `TPS`s corresponding to the parameters for the `Descriptor` specified by `use`. +Default value is `GTPSA.desc_current`. + +### Input +- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` + +### Output +- `k` -- `Vector` containing unit `TPS`s corresponding to each parameter +""" +function params(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{TPS} + nv = numvars(use) + np = numparams(use) + k = Vector{TPS}(undef, np) + for i=nv+1:nv+np + t = TPS(use=use) + t[i] = 1.0 + k[i-nv] = t + end + return k +end + + +""" + complexvars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{ComplexTPS} + +Returns `ComplexTPS`s corresponding to the variables for the `Descriptor` specified by `use`. +Default value is `GTPSA.desc_current`. + +### Input +- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` + +### Output +- `x` -- `Vector` containing unit `ComplexTPS`s corresponding to each variable +""" +function complexvars(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{ComplexTPS} + nv = numvars(use) + x = Vector{ComplexTPS}(undef, nv) + for i=1:nv + t = ComplexTPS(use=use) + t[i] = 1.0 + x[i] = t + end + return x +end + +""" + complexparams(d::Descriptor=GTPSA.desc_current)::Vector{ComplexTPS} + +Returns `ComplexTPS`s corresponding to the parameters for the `Descriptor` specified by `use`. +Default value is `GTPSA.desc_current`. + +### Input +- `use` -- (Optional) Specify which TPSA `Descriptor` to use, default is `GTPSA.desc_current` + +### Output +- `k` -- `Vector` containing unit `ComplexTPS`s corresponding to each parameter +""" +function complexparams(use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current)::Vector{ComplexTPS} + nv = numvars(use) + np = numparams(use) + k = Vector{ComplexTPS}(undef, np) + for i=nv+1:nv+np + t = ComplexTPS(use=use) + t[i] = 1.0 + k[i-nv] = t + end + return k +end + +""" + mono(v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing, use::Descriptor=GTPSA.desc_current)::TPS + +Returns a `TPS` corresponding to a specific monomial, specified using the variable/parameter index, or +monomial indexing-by-order OR monomial indexing-by-sparse monomial. + +### Input +- `v` -- An integer (for variable index), an array of orders for each variable (for indexing-by-order), or an array of pairs (sparse monomial) +- `param` -- (Keyword argument, optional) An integer for the parameter index +- `params` -- (Keyword argument, optional) An array of pairs for sparse-monomial indexing +- `use` -- (Keyword argument, optional) The descriptor to use to generate the monomial. Default is most recently-defined. + +# Examples: Variable/Parameter Index: +```julia-repl +julia> d = Descriptor(3,10,2,10); + +julia> mono(1) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 1 0 0 0 0 + + +julia> mono(2, use=d) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 0 1 0 0 0 + + +julia> mono(param=2) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 0 0 0 0 1 +``` + +# Examples: Monomial Index-by-Order +```julia-repl +julia> mono([1]) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 1 0 0 0 0 + + +julia> mono([0,1]) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 0 1 0 0 0 + + +julia> mono([0,0,0,0,1], use=d) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 0 0 0 0 1 + + +julia> mono([1,0,0,0,1]) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 2 1 0 0 0 1 +``` + +# Examples: Monomial Index-by-Sparse Monomial +```julia-repl +julia> mono([1=>1]) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 1 0 0 0 0 + + +julia> mono([2=>1]) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 1 0 1 0 0 0 + + +julia> mono([1=>1], params=[2=>1], use=d) +TPS: + Coefficient Order Exponent + 1.0000000000000000e+00 2 1 0 0 0 1 +``` +""" +function mono(v::Union{TPSIndexType,Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing, use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current) + return low_mono(TPS, use, v, param, params) +end + +function complexmono(v::Union{TPSIndexType,Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing, use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current) + return low_mono(ComplexTPS, use, v, param, params) +end + +# Variable/parameter: +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Integer, param::Nothing, params::Nothing) + t = T(use=d) + seti!(t.tpsa, Cint(v), convert(numtype(T), 0.0), convert(numtype(T), 1.0)) + return t +end + +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Nothing, param::Integer, params::Nothing) + t = T(use=d) + desc = unsafe_load(mad_tpsa_desc(t.tpsa)) + nv = desc.nv # TOTAL NUMBER OF VARS!!!! + seti!(t.tpsa, Cint(param) + nv, convert(numtype(T), 0.0), convert(numtype(T), 1.0)) + return t +end + +# Default to scalar value if nothing passed +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Nothing) + t = T(use=d) + t[0] = 1.0 + return t +end + +# Monomial by order: +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::MIndexType, param::Nothing, params::Nothing) + t = T(use=d) + t[v] = 1.0 + return t +end + +# Monomial by sparse monomial: +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::SMIndexType, param::Nothing, params::SMIndexType) + t = T(use=d) + t[v, params=params] = 1.0 + return t +end + +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::SMIndexType, param::Nothing, params::Nothing) + t = T(use=d) + # Need to create array of orders with length nv + np + t[v] = 1.0 + return t +end + +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v::Nothing, param::Nothing, params::SMIndexType) + t = T(use=d) + t[params=params] = 1.0 + return t +end + +# Throw error if no above use cases satisfied: +function low_mono(T::Type, d::Union{Descriptor,TPS,ComplexTPS}, v, param, params) + error("Invalid monomial specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") +end + diff --git a/src/descriptor.jl b/src/descriptor.jl new file mode 100644 index 00000000..46dfb625 --- /dev/null +++ b/src/descriptor.jl @@ -0,0 +1,89 @@ +# Wrapper struct for Ptr{Desc} +struct Descriptor + desc::Ptr{Desc} + function Descriptor(desc::Ptr{Desc})::Descriptor + d = new(desc) + return d + end +end + +# Descriptor outer constructors +""" + Descriptor(nv::Integer, mo::Integer)::Descriptor + +Creates a TPSA `Descriptor` with `nv` variables, and a maximum truncation order `mo`. + +### Input +- `nv` -- Number of variables in the TPSA +- `mo` -- Maximum truncation order of the TPSA +""" +function Descriptor(nv::Integer, mo::Integer)::Descriptor + d = Descriptor(mad_desc_newv(convert(Cint, nv), convert(Cuchar, mo))) + GTPSA.desc_current = d + return d +end + +""" + Descriptor(vos::Vector{<:Integer}, mo::Integer)::Descriptor + +Creates a TPSA `Descriptor` with `length(vos)` variables with individual truncation +orders specified in the Vector `vos`, and a maximum truncation order `mo` for the TPSA. + +### Input +- `vos` -- `Vector` of the individual truncation orders of each variable +- `mo` -- Maximum truncation order of the TPSA, <= sum(vos) +""" +function Descriptor(vos::Vector{<:Integer}, mo::Integer)::Descriptor + all(vos .<= mo) == true || error("Atleast one variable truncation order is > the maximum truncation order!") + mo <= sum(vos) || (@info "Maximum order too high: setting maximum order = sum($vos) = $(sum(vos))"; mo = sum(vos)) + nv = length(vos) + np = 0 + po = 0 + no = vos + d = Descriptor(mad_desc_newvpo(convert(Cint, nv), convert(Cuchar, mo), convert(Cint, np), convert(Cuchar, po), convert(Vector{Cuchar}, no))) + GTPSA.desc_current = d + return d +end + +""" + Descriptor(nv::Integer, mo::Integer, np::Integer, po::Integer)::Descriptor + +Creates a TPSA `Descriptor` with `nv` variables and `np` parameters. The maximum +truncation order is `mo` (including the parameters), and the truncation order for +the parameters part of a monomial is `po`. + +### Input +- `nv` -- Number of variables in the TPSA +- `mo` -- Maximum truncation order of the TPSA including variables and parameters +- `np` -- Number of parameters in the TPSA +- `po` -- Truncation order of the parameters part of a monomial +""" +function Descriptor(nv::Integer, mo::Integer, np::Integer, po::Integer)::Descriptor + d = Descriptor(mad_desc_newvp(convert(Cint, nv), convert(Cuchar, mo), convert(Cint, np), convert(Cuchar, po))) + GTPSA.desc_current = d + return d +end + + +""" + Descriptor(vos::Vector{<:Integer}, mo::Integer, pos::Vector{<:Integer}, po::Integer)::Descriptor + +Creates a TPSA `Descriptor` with `length(vos)` variables with individual truncation +orders specified in `vos`, and `length(pos)` parameters with individual truncation +orders specified in `pos`. The maximum truncation order including both variables and +parameters is `mo`, and the truncation order for just the parameters part of the is `po`. + +### Input +- `vos` -- `Vector` of the individual truncation orders of each variable +- `mo` -- Maximum truncation order of the TPSA including variables and parameters +- `pos` -- `Vector` of the individual truncation orders of each parameter +- `po` -- Truncation order of the parameters part of a monomial +""" +function Descriptor(vos::Vector{<:Integer}, mo::Integer, pos::Vector{<:Integer}, po::Integer)::Descriptor + nv = length(vos) + np = length(pos) + no = vcat(vos,pos) + d = Descriptor(mad_desc_newvpo(convert(Cint, nv), convert(Cuchar, mo), convert(Cint, np), convert(Cuchar, po), convert(Vector{Cuchar}, no))) + GTPSA.desc_current = d + return d +end \ No newline at end of file diff --git a/src/fast_gtpsa.jl b/src/fast_gtpsa.jl index 87a22fdd..97fa7cb2 100644 --- a/src/fast_gtpsa.jl +++ b/src/fast_gtpsa.jl @@ -234,7 +234,7 @@ end function ±(t1::TPS, a::Real)::Ptr{RTPSA} tpsa = get_rtemp!(t1) mad_tpsa_copy!(t1.tpsa, tpsa) - mad_tpsa_set0!(tpsa, 1., convert(Float64,a)) + mad_tpsa_seti!(tpsa, Cint(0),1., convert(Float64,a)) return tpsa end @@ -258,7 +258,7 @@ function ±(tpsa1::Ptr{RTPSA},t1::TPS)::Ptr{RTPSA} end function ±(tpsa1::Ptr{RTPSA}, a::Real)::Ptr{RTPSA} - mad_tpsa_set0!(tpsa1, 1., convert(Float64,a)) + mad_tpsa_seti!(tpsa1, Cint(0), 1., convert(Float64,a)) return tpsa1 end @@ -276,7 +276,7 @@ end function ±(ct1::ComplexTPS, a::Number)::Ptr{CTPSA} ctpsa = get_ctemp!(ct1) mad_ctpsa_copy!(ct1.tpsa, ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64,1), convert(ComplexF64,a)) + mad_ctpsa_seti!(ctpsa, Cint(0), convert(ComplexF64,1), convert(ComplexF64,a)) return ctpsa end @@ -300,7 +300,7 @@ function ±(ctpsa1::Ptr{CTPSA}, ct1::ComplexTPS)::Ptr{CTPSA} end function ±(ctpsa1::Ptr{CTPSA}, a::Number)::Ptr{CTPSA} - mad_ctpsa_set0!(ctpsa1, convert(ComplexF64,1), convert(ComplexF64,a)) + mad_ctpsa_seti!(ctpsa1, Cint(0), convert(ComplexF64,1), convert(ComplexF64,a)) return ctpsa1 end @@ -323,7 +323,7 @@ end function ±(t1::TPS, a::Complex)::Ptr{CTPSA} ctpsa = get_ctemp!(t1) mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) + mad_ctpsa_seti!(ctpsa, Cint(0),convert(ComplexF64, 1), convert(ComplexF64, a)) return ctpsa end @@ -334,7 +334,7 @@ end function ±(tpsa1::Ptr{RTPSA}, a::Complex)::Ptr{CTPSA} ctpsa = get_ctemp_low!(tpsa1) mad_ctpsa_cplx!(tpsa1, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) + mad_ctpsa_seti!(ctpsa, Cint(0),convert(ComplexF64, 1), convert(ComplexF64, a)) rel_rtemp!(tpsa1) return ctpsa end @@ -378,14 +378,14 @@ end function ∓(t1::TPS, a::Real)::Ptr{RTPSA} tpsa = get_rtemp!(t1) mad_tpsa_copy!(t1.tpsa, tpsa) - mad_tpsa_set0!(tpsa, 1., convert(Float64, -a)) + mad_tpsa_seti!(tpsa, Cint(0), 1., convert(Float64, -a)) return tpsa end function ∓(a::Real, t1::TPS)::Ptr{RTPSA} tpsa = get_rtemp!(t1) mad_tpsa_scl!(t1.tpsa, -1., tpsa) - mad_tpsa_set0!(tpsa, 1., convert(Float64, a)) + mad_tpsa_seti!(tpsa, Cint(0), 1., convert(Float64, a)) return tpsa end @@ -406,13 +406,13 @@ function ∓(tpsa1::Ptr{RTPSA}, t1::TPS)::Ptr{RTPSA} end function ∓(tpsa1::Ptr{RTPSA}, a::Real)::Ptr{RTPSA} - mad_tpsa_set0!(tpsa1, 1., convert(Float64, -a)) + mad_tpsa_seti!(tpsa1, Cint(0), 1., convert(Float64, -a)) return tpsa1 end function ∓(a::Real, tpsa1::Ptr{RTPSA})::Ptr{RTPSA} mad_tpsa_scl!(tpsa1, -1., tpsa1) - mad_tpsa_set0!(tpsa1, 1., convert(Float64, a)) + mad_tpsa_seti!(tpsa1, Cint(0), 1., convert(Float64, a)) return tpsa1 end @@ -426,14 +426,14 @@ end function ∓(ct1::ComplexTPS, a::Number)::Ptr{CTPSA} ctpsa = get_ctemp!(ct1) mad_ctpsa_copy!(ct1.tpsa, ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1.), convert(ComplexF64, -a)) + mad_ctpsa_seti!(ctpsa, Cint(0), convert(ComplexF64, 1.), convert(ComplexF64, -a)) return ctpsa end function ∓(a::Number, ct1::ComplexTPS)::Ptr{CTPSA} ctpsa = get_ctemp!(ct1) mad_ctpsa_scl!(ct1.tpsa, convert(ComplexF64,-1.), ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64,1.), convert(ComplexF64, a)) + mad_ctpsa_seti!(ctpsa, Cint(0), convert(ComplexF64,1.), convert(ComplexF64, a)) return ctpsa end @@ -454,13 +454,13 @@ function ∓(ctpsa1::Ptr{CTPSA}, ct1::ComplexTPS)::Ptr{CTPSA} end function ∓(ctpsa1::Ptr{CTPSA}, a::Number)::Ptr{CTPSA} - mad_ctpsa_set0!(ctpsa1, convert(ComplexF64,1.), convert(ComplexF64, -a)) + mad_ctpsa_seti!(ctpsa1, Cint(0), convert(ComplexF64,1.), convert(ComplexF64, -a)) return ctpsa1 end function ∓(a::Number, ctpsa1::Ptr{CTPSA})::Ptr{CTPSA} mad_ctpsa_scl!(ctpsa1, convert(ComplexF64, -1.), ctpsa1) - mad_ctpsa_set0!(ctpsa1, convert(ComplexF64, 1.), convert(ComplexF64, a)) + mad_ctpsa_seti!(ctpsa1, Cint(0), convert(ComplexF64, 1.), convert(ComplexF64, a)) return ctpsa1 end @@ -480,7 +480,7 @@ end function ∓(t1::TPS, a::Complex)::Ptr{CTPSA} ctpsa = get_ctemp!(t1) mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1), convert(ComplexF64, -a)) + mad_ctpsa_seti!(ctpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64, -a)) return ctpsa end @@ -488,7 +488,7 @@ function ∓(a::Complex, t1::TPS)::Ptr{CTPSA} ctpsa = get_ctemp!(t1) mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ctpsa) mad_ctpsa_scl!(ctpsa, convert(ComplexF64, -1), ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1), convert(ComplexF64,a)) + mad_ctpsa_seti!(ctpsa,Cint(0), convert(ComplexF64, 1), convert(ComplexF64,a)) return ctpsa end @@ -508,7 +508,7 @@ function ∓(tpsa1::Ptr{RTPSA}, a::Complex)::Ptr{CTPSA} ctpsa = get_ctemp_low!(tpsa1) mad_ctpsa_cplx!(tpsa1, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ctpsa) rel_temp!(tpsa1) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1), convert(ComplexF64, -a)) + mad_ctpsa_seti!(ctpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64, -a)) return ctpsa end @@ -517,7 +517,7 @@ function ∓(a::Complex, tpsa1::Ptr{RTPSA})::Ptr{CTPSA} mad_ctpsa_cplx!(tpsa1, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ctpsa) rel_temp!(tpsa1) mad_ctpsa_scl!(ctpsa, convert(ComplexF64, -1), ctpsa) - mad_ctpsa_set0!(ctpsa, convert(ComplexF64, 1), convert(ComplexF64,a)) + mad_ctpsa_seti!(ctpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64,a)) return ctpsa end function ∓(ctpsa1::Ptr{CTPSA}, t1::TPS)::Ptr{CTPSA} diff --git a/src/getset.jl b/src/getset.jl index f1c0d175..b3d575d7 100644 --- a/src/getset.jl +++ b/src/getset.jl @@ -1,77 +1,182 @@ -numtype(t::TPS) = Float64 -numtype(ct::ComplexTPS) = ComplexF64 -numtype(::Type{TPS}) = Float64 -numtype(::Type{ComplexTPS}) = ComplexF64 +# --- Setters --- +seti!(t::Ptr{RTPSA}, i::Cint, a::Cdouble, b::Cdouble) = mad_tpsa_seti!(t, i, a, b) +seti!(t::Ptr{CTPSA}, i::Cint, a::ComplexF64, b::ComplexF64) = mad_ctpsa_seti!(t, i, a, b) +setm!(t::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}, a::Float64, b::Float64) = mad_tpsa_setm!(t, n, m, a, b) +setm!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}, a::ComplexF64, b::ComplexF64) = mad_ctpsa_setm!(t, n, m, a, b) +setsm!(t::Ptr{RTPSA}, n::Cint, m::Vector{Cint}, a::Float64, b::Float64)= mad_tpsa_setsm!(t, n, m, a, b) +setsm!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cint}, a::ComplexF64, b::ComplexF64)= mad_ctpsa_setsm!(t, n, m, a, b) +setv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Vector{Cdouble}) = mad_tpsa_setv!(t, i, n, v) +setv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Vector{ComplexF64}) = mad_ctpsa_setv!(t, i, n, v) + +# All +function setindex!(t::Union{TPS,ComplexTPS}, v::Union{AbstractVector{<:Number},Number}, idx::Union{TPSIndexType,AbstractVector{<:Integer},Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing) + lowset!(t, v, idx, param, params) +end -lowtype(t::TPS) = Ptr{RTPSA} -lowtype(ct::ComplexTPS) = Ptr{CTPSA} -lowtype(::Type{TPS}) = Ptr{RTPSA} -lowtype(::Type{ComplexTPS}) = Ptr{CTPSA} +# Flat index +function lowset!(t::Union{TPS,ComplexTPS}, v::Number, i::Union{Nothing,Integer}, param::Union{Nothing,Integer}, params::Nothing) + if isnothing(i) && isnothing(param) + return + elseif !isnothing(i) && !isnothing(param) + error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") + elseif isnothing(param) + seti!(t.tpsa, Cint(i), (numtype(t))(0), (numtype(t))(v)) + else + nv = numvars(t) + seti!(t.tpsa, Cint(nv+param), (numtype(t))(0), (numtype(t))(v)) + end +end -# --- Setters --- -function setindex!(t::TPS, v::Real, ords::Integer...) - mad_tpsa_setm!(t.tpsa, convert(Cint, length(ords)), convert(Vector{Cuchar}, [ords...]), 0.0, convert(Cdouble, v)) +# Flat index vectorized +function lowset!(t::Union{TPS,ComplexTPS}, v::AbstractVector{<:Number}, idxs::AbstractVector{<:Integer}, param::Nothing, params::Nothing) + Base.require_one_based_indexing(v,idxs) + length(v) == length(idxs) || throw(DimensionMismatch("Tried to assign $(length(v)) elements to $(length(idxs)) destinations")) + for i=1:length(idxs) + seti!(t.tpsa, Cint(idxs[i]), (numtype(t))(0),(numtype(t))(v[i])) + end end -function setindex!(t::TPS, v::Real, vars::Pair{<:Integer, <:Integer}...; params::Vector{<:Pair{<:Integer,<:Integer}}=Pair{Int,Int}[]) - sm, n = pairs_to_sm(t, vars, params=params) - mad_tpsa_setsm!(t.tpsa, n, sm, 0.0, convert(Cdouble, v)) +# Monomial +function lowset!(t::Union{TPS,ComplexTPS}, v::Number, ords::MIndexType, param::Nothing, params::Nothing) + setm!(t.tpsa, convert(Cint, length(ords)), collect(Cuchar, ords), (numtype(t))(0), (numtype(t))(v)) end -function setindex!(ct::ComplexTPS, v::Number, ords::Integer...) - mad_ctpsa_setm!(ct.tpsa, convert(Cint, length(ords)), convert(Vector{Cuchar}, [ords...]), convert(ComplexF64, 0), convert(ComplexF64, v)) +# By sparse monomial +function lowset!(t::Union{TPS,ComplexTPS}, v::Number, vars::SMIndexType, param::Nothing, params::Union{SMIndexType,Nothing}) + sm, n = pairs_to_sm(t, vars, params=params) + setsm!(t.tpsa, n, sm, (numtype(t))(0), (numtype(t))(v)) end -function setindex!(ct::ComplexTPS, v::Number, vars::Pair{<:Integer, <:Integer}...; params::Vector{<:Pair{<:Integer,<:Integer}}=Pair{Int,Int}[]) - sm, n = pairs_to_sm(ct, vars, params=params) - mad_ctpsa_setsm!(ct.tpsa, n, sm, convert(ComplexF64, 0), convert(ComplexF64, v)) +# Sparse monomial with nothing for vars +function lowset!(t::Union{TPS,ComplexTPS}, v::Number, vars::Nothing, param::Nothing, params::SMIndexType) + sm, n = pairs_to_sm(t, Pair{Int,Int}[], params=params) + setsm!(t.tpsa, n, sm, (numtype(t))(0), (numtype(t))(v)) end +# In case someone forgets tuple: +lowset!(t, v, idx, param, params) = error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") + # --- Getters --- +geti(t::Ptr{RTPSA}, i::Cint) = mad_tpsa_geti(t, i) +geti(t::Ptr{CTPSA}, i::Cint) = mad_ctpsa_geti(t, i) getm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}) = mad_tpsa_getm(t, n, m) getm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}) = mad_ctpsa_getm(t, n, m) getsm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cint})= mad_tpsa_getsm(t, n, m) getsm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cint})= mad_ctpsa_getsm(t, n, m) -function getindex(t::Union{TPS,ComplexTPS}, ords::Integer...) - return getm(t.tpsa, convert(Cint, length(ords)), convert(Vector{Cuchar}, [ords...])) +# All +function getindex(t::Union{TPS,ComplexTPS}, idx::Union{AbstractVector{<:Integer},TPSIndexType,Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType,Nothing}=nothing) + #println(typeof(t)) + #println(typeof(idx)) + #println(typeof(param)) + #println(typeof(params)) + return lowget(t, idx, param, params) +end + +# To override Base number.jl +getindex(t::Union{ComplexTPS, TPS}, idx::Integer) = lowget(t, idx, nothing, nothing) + +# Flat index +function lowget(t::Union{TPS,ComplexTPS}, i::Union{Nothing,Integer}, param::Union{Nothing,Integer}, params::Nothing) + if isnothing(i) && isnothing(param) + return t + elseif !isnothing(i) && !isnothing(param) + error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") + elseif isnothing(param) + return geti(t.tpsa, Cint(i)) + else + nv = numvars(t) + return geti(t.tpsa, Cint(nv+param)) + end +end + +# Flat index vectorized +function lowget(t::Union{TPS,ComplexTPS}, idxs::AbstractVector{<:Integer}, param::Nothing, params::Nothing) + Base.require_one_based_indexing(idxs) + v = Vector{numtype(t)}(undef, length(idxs)) + for i=1:length(idxs) + v[i] = geti(t.tpsa, Cint(idxs[i])) + end + return v +end + +# Monomial +function lowget(t::Union{TPS,ComplexTPS}, ords::MIndexType, param::Nothing, params::Nothing) + return getm(t.tpsa, convert(Cint, length(ords)), collect(Cuchar, ords)) end -function getindex(t::Union{TPS,ComplexTPS}, vars::Pair{<:Integer, <:Integer}...; params::Vector{<:Pair{<:Integer,<:Integer}}=Pair{Int,Int}[]) - # use sparse monomial getter +# By sparse monomial +function lowget(t::Union{TPS,ComplexTPS}, vars::SMIndexType, param::Nothing, params::Union{SMIndexType,Nothing}) sm, n = pairs_to_sm(t, vars, params=params) return getsm(t.tpsa, n, sm) end -function getindex(t::Union{TPS,ComplexTPS}, ords::Union{Integer,Colon}...) - #= - if !(ords[1:end-1] isa Tuple{Vararg{Integer}}) - error("Invalid monomial index: colon must appear at end.") - end=# - return slice(t, setup_mono(t,ords,nothing,nothing), false) +# Sparse monomial with nothing for vars +function lowget(t::Union{TPS,ComplexTPS}, vars::Nothing, param::Nothing, params::SMIndexType) + sm, n = pairs_to_sm(t, Pair{Int,Int}[], params=params) + return getsm(t.tpsa, n, sm) end -function getindex(t::Union{TPS,ComplexTPS}, vars::Union{Pair{<:Integer, <:Integer}, Colon}...; params::Vector{<:Pair{<:Integer,<:Integer}}=Pair{Int,Int}[]) - return slice(t, setup_mono(t, vars, nothing, params), false) +lowget(t, idx, param, params) = error("Invalid monomial index specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") + +# --- length --- +len(t::Ptr{RTPSA}) = mad_tpsa_len(t) +len(t::Ptr{CTPSA}) = mad_ctpsa_len(t) + +""" + length(t::Union{TPS,ComplexTPS} + +Returns the maximum number of monomials (including the scalar part) +in the `TPS`/`ComplexTPS` given its `Descriptor`. +""" +length(t::Union{TPS,ComplexTPS}) = len(t.tpsa) + +firstindex(t::Union{TPS,ComplexTPS}) = 0 +lastindex(t::Union{TPS,ComplexTPS}) = length(t)-1 + +# --- Slicing (getter) --- + +# Vectors (which will be Vector{Any}) must be converted to tuples so SM or M indexing can be resolved: +const SMColonIndexType = Tuple{Vararg{Union{Pair{<:Integer,<:Integer},Colon}}} +const MColonIndexType =Tuple{Vararg{Union{Integer,Colon}}} +const TPSColonIndexType = Union{MColonIndexType, + SMColonIndexType, + Vector{<:Any}} + +function getindex(t::Union{TPS,ComplexTPS}, v::TPSColonIndexType; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) + if (v isa Vector) + par_mono = setup_mono(t, tuple(v...), param, params) + else + par_mono = setup_mono(t, v, param, params) + end + return slice(t, par_mono, false) end -getindex(t::Union{TPS,ComplexTPS}) = t +# For flat indexing: +function getindex(t::Union{TPS,ComplexTPS}, v::Integer, c::Colon) + par_mono = setup_mono(t, v, nothing, nothing) + return slice(t, par_mono,false) +end -#= -function getindex(::TPS) - return TPS[] +function getindex(t::Union{TPS,ComplexTPS}, c::Colon; param::Union{Integer,Nothing}=nothing) + if isnothing(param) + return t + else + par_mono = setup_mono(t, nothing, param, nothing) + return slice(t, par_mono,false) + end end -=# + # --- par --- """ - par(t::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer, <:Any}}, Tuple{Vararg{Union{<:Integer,Pair{<:Integer,<:Integer},<:Colon}}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) + par(t::Union{TPS,ComplexTPS}, v::Union{TPSColonIndexType, Vector{Pair{<:Integer,<:Integer}}, Vector{<:Integer}, Integer, Colon, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) Extracts a polynomial from the TPS containing the specified monomial, and removes the monomial. ### Input -- `v` -- An integer (for variable index), an array of orders for each variable (for indexing-by-order), or an array of pairs (sparse monomial) +- `v` -- An integer (for variable index), an array/tuple of orders for each variable (for indexing-by-order), or an array/tuple of pairs (sparse monomial) - `param` -- (Keyword argument, optional) An integer for the parameter index - `params` -- (Keyword argument, optional) An array of pairs for sparse-monomial indexing @@ -132,60 +237,59 @@ TPS: 3.0000000000000000e+00 7 2 1 1 2 1 | 0 0 ``` """ -function par(t::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer, <:Any}}, Tuple{Vararg{Union{<:Integer,Pair{<:Integer,<:Integer},<:Colon}}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) - if (v isa Vector) && !(last(v) isa Colon) - par_mono = setup_mono(t, tuple(v...,:), param, params) +function par(t::Union{TPS,ComplexTPS}, v::Union{TPSColonIndexType, Vector{Pair{<:Integer,<:Integer}}, Vector{<:Integer}, Integer, Colon, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) + if (v isa Vector) + tmpv = tuple(v...) + if tmpv isa MColonIndexType # because par-ing, must add colon + par_mono = setup_mono(t, tuple(tmpv...,:), param, params) + else + par_mono = setup_mono(t, tmpv, param, params) + end else par_mono = setup_mono(t, v, param, params) end return slice(t, par_mono) end -# Variable/parameter: +# Flat index: function setup_mono(t1::Union{TPS,ComplexTPS}, v::Integer, param::Nothing, params::Nothing)::Vector{Cuchar} par_mono = ones(Cuchar, v+1).*0xff par_mono[v] = 0x1 return par_mono end -function setup_mono(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Integer, params::Nothing)::Vector{Cuchar} - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) - nv = desc.nv # TOTAL NUMBER OF VARS!!!! +function setup_mono(t1::Union{TPS,ComplexTPS}, v::Union{Nothing,Colon}, param::Integer, params::Nothing)::Vector{Cuchar} + nv = numvars(t1) # TOTAL NUMBER OF VARS!!!! par_mono = ones(Cuchar, param+nv+1).*0xff par_mono[nv+param] = 0x1 return par_mono end -#= -# Default to scalar part as TPS if nothing passed: -function setup_mono(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Nothing)::Vector{Cuchar} - return [0x0] -end -=# + # Monomial by order: # This one should ALWAYS be called by par or splicing colon IS in the tuple or vector somewhere -function setup_mono(t1::Union{TPS,ComplexTPS}, v::Union{Tuple{Vararg{Union{<:Integer,<:Colon}}},Vector{<:Any}}, param::Nothing, params::Nothing)::Vector{Cuchar} - return [replace(x-> x isa Colon ? 0xff::Cuchar : convert(Cuchar, x)::Cuchar, v)...] +function setup_mono(t1::Union{TPS,ComplexTPS}, v::MColonIndexType, param::Nothing, params::Nothing)::Vector{Cuchar} + return collect(replace(x-> x isa Colon ? 0xff::Cuchar : convert(Cuchar, x)::Cuchar, v)) end # By definition, sparse monomial makes everything else zero. SO if we reach this, it is automatically # assumed that everything else is colon except those explictly made ix_var=>0 # Monomial by sparse monomial: -function setup_mono(t1::Union{TPS,ComplexTPS}, v::Union{Vector{<:Pair{<:Integer,<:Integer}}, Tuple{Vararg{Union{Pair{<:Integer,<:Integer},<:Colon}}}}, param::Nothing, params::Vector{<:Pair{<:Integer,<:Integer}})::Vector{Cuchar} +function setup_mono(t1::Union{TPS,ComplexTPS}, v::SMColonIndexType, param::Nothing, params::SMIndexType)::Vector{Cuchar} # Need to create array of orders with length nv + np ords, ___ = pairs_to_m(t1,filter(x->!(x isa Colon), v),params=params,zero_mono=false) - return [ords..., 0xff] + return vcat(ords, 0xff) end -function setup_mono(t1::Union{TPS,ComplexTPS}, v::Union{Vector{<:Pair{<:Integer,<:Integer}}, Tuple{Vararg{Union{Pair{<:Integer,<:Integer},<:Colon}}}}, param::Nothing, params::Nothing)::Vector{Cuchar} +function setup_mono(t1::Union{TPS,ComplexTPS}, v::SMColonIndexType, param::Nothing, params::Nothing)::Vector{Cuchar} # Need to create array of orders with length nv + np ords, ___ = pairs_to_m(t1,filter(x->!(x isa Colon), v),zero_mono=false) - return [ords..., 0xff] + return vcat(ords, 0xff) end -function setup_mono(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Vector{<:Pair{<:Integer,<:Integer}})::Vector{Cuchar} +function setup_mono(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Nothing, params::SMIndexType)::Vector{Cuchar} # Need to create array of orders with length nv + np ords, ___ = pairs_to_m(t1,Pair{Int,Int}[],params=params,zero_mono=false) - return [ords..., 0xff] + return vcat(ords, 0xff) end @@ -194,10 +298,12 @@ function setup_mono(t1::Union{TPS,ComplexTPS}, v, param, params) error("Invalid monomial specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") end +idxm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}) = (@inline; mad_tpsa_idxm(t, n, m)) +idxm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}) = (@inline; mad_ctpsa_idxm(t, n, m)) + function slice(t1::Union{TPS,ComplexTPS}, par_mono::Vector{Cuchar}, par_it=true) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) - nv = desc.nv # TOTAL NUMBER OF VARS!!!! - np = desc.np + nv = numvars(t1) + np = numparams(t1) t = zero(t1) v = Cint(length(par_mono)) coef = Ref{numtype(t)}() @@ -214,10 +320,9 @@ function slice(t1::Union{TPS,ComplexTPS}, par_mono::Vector{Cuchar}, par_it=true) tmp = zeros(Cuchar, np+nv) tmp[invalid_idxs] .= mono[invalid_idxs] tmp[v+1:end] .= mono[v+1:end] - t[tmp...] = coef[] + t[tmp] = coef[] else - t[mono...] = coef[] - + t[idx] = coef[] end end end @@ -227,11 +332,11 @@ function slice(t1::Union{TPS,ComplexTPS}, par_mono::Vector{Cuchar}, par_it=true) end # --- gradient, jacobian, hessian getters --- -getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Union{Ptr{Cdouble},Vector{Cdouble}}) = (@inline; mad_tpsa_getv!(t, i, n, v)) -getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Union{Ptr{ComplexF64},Vector{ComplexF64}}) = (@inline; mad_ctpsa_getv!(t, i, n, v)) +getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v) = (@inline; mad_tpsa_getv!(t, i, n, v)) +getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v) = (@inline; mad_ctpsa_getv!(t, i, n, v)) """ - gradient!(result::Vector{<:Union{Float64,ComplexF64}}, t::Union{TPS,ComplexTPS}; include_params=false) + gradient!(result, t::Union{TPS,ComplexTPS}; include_params=false) Extracts the first-order partial derivatives (evaluated at 0) from the TPS and fills the `result` vector in-place. The partial derivatives wrt the parameters will also be extracted @@ -244,18 +349,19 @@ in the TPS. - `include_params` -- (Optional) Extract partial derivatives wrt parameters. Default is false ### Output -- `result` -- Preallocated `Vector` to fill with the gradient of the TPS +- `result` -- Vector to fill with the gradient of the TPS, must be 1-based indexing """ -function gradient!(result::Vector{<:Union{Float64,ComplexF64}}, t::Union{TPS,ComplexTPS}; include_params=false) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)) - n = desc.nv +function gradient!(result, t::Union{TPS,ComplexTPS}; include_params=false) + Base.require_one_based_indexing(result) + n = numvars(t) if include_params - n += desc.np + n += numparams(t) end if length(result) != n error("Incorrect size for result") end getv!(t.tpsa, Cint(1), n, result) + return end """ @@ -274,10 +380,9 @@ first-order monomial coefficients already in the TPS. - `grad` -- Gradient of the TPS """ function gradient(t::Union{TPS,ComplexTPS}; include_params=false) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)) - n = desc.nv + n = numvars(t) if include_params - n += desc.np + n += numparams(t) end grad = Vector{numtype(t)}(undef, n) getv!(t.tpsa, Cint(1), n, grad) @@ -285,7 +390,7 @@ function gradient(t::Union{TPS,ComplexTPS}; include_params=false) end """ - jacobian!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) + jacobian!(result, m; include_params=false) Extracts the first-order partial derivatives (evaluated at 0) from the Vector of TPSs. and fills the `result` matrix in-place. The partial derivatives wrt the parameters will @@ -294,33 +399,33 @@ is not calculating anything - just extracting the first-order monomial coefficie in the TPSs. ### Input -- `m` -- `Vector` of TPSs. to extract the Jacobian from +- `m` -- Vector of TPSs to extract the Jacobian from, must be 1-based indexing - `include_params` -- (Optional) Extract partial derivatives wrt parameters. Default is false ### Output -- `result` -- Preallocated matrix to fill with the Jacobian of `m` +- `result` -- Matrix to fill with the Jacobian of `m`, must be 1-based indexing """ -function jacobian!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(first(m).tpsa).d)) - n = desc.nv +function jacobian!(result, m; include_params=false) + Base.require_one_based_indexing(result, m) + n = numvars(first(m)) if include_params - n += desc.np + n += numparams(first(m)) end - if size(result)[2] != n + if size(result) != (length(m), n) error("Incorrect size for result") end - grad = Vector{numtype(first(m))}(undef, n) - # This is not fully in-place technically, bc Julia is column-major and - # filling each row in place without allocating temp would require row-major - # So there are allocations for the array grad - for i=1:length(m) - getv!(m[i].tpsa, Cint(1), n, grad) - result[i,:] = grad + + + for i=1:n + for j=1:length(m) + result[j,i] = geti(m[j].tpsa, Cint(i)) + end end + return end """ - jacobian(m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) + jacobian(m; include_params=false) Extracts the first-order partial derivatives (evaluated at 0) from the Vector of TPSs. The partial derivatives wrt the parameters will also be extracted when the `include_params` @@ -328,51 +433,46 @@ flag is set to `true`. Note that this function is not calculating anything - jus the first-order monomial coefficients already in the TPSs. ### Input -- `m` -- `Vector` of TPSs. to extract the Jacobian from +- `m` -- Vector of TPSs to extract the Jacobian from, must be 1-based indexing - `include_params` -- (Optional) Extract partial derivatives wrt parameters. Default is false ### Output - `J` -- Jacobian of `m` """ -function jacobian(m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(first(m).tpsa).d)) - n = desc.nv +function jacobian(m; include_params=false) + Base.require_one_based_indexing(m) + n = numvars(first(m)) if include_params - n += desc.np + n += numparams(first(m)) end J = Matrix{numtype(first(m))}(undef, length(m), n) - grad = Vector{numtype(first(m))}(undef, n) - for i=1:length(m) - mad_tpsa_getv!(m[i].tpsa, Cint(1), n, grad) - J[i,:] = grad - end + jacobian!(J, m; include_params=include_params) return J end """ - jacobiant!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) + jacobiant!(result, m; include_params=false) Extracts the first-order partial derivatives (evaluated at 0) from the Vector of TPSs, -as the transpose of the Jacobian. Because of Julia's column-major indexing vs. C's row-major, -this routine will be slightly faster than using `jacobian!` if the transpose of the Jacobian is -needed. The partial derivatives wrt the parameters will also be extracted when the `include_params` -flag is set to `true`. Note that this function is not calculating anything - just extracting the -first-order monomial coefficients already in the TPSs and filling `result`. +as the transpose of the Jacobian. The partial derivatives wrt the parameters will also +be extracted when the `include_params` flag is set to `true`. Note that this function is +not calculating anything - just extracting the first-order monomial coefficients already +in the TPSs and filling `result`. ### Input -- `m` -- `Vector` of TPSs. to extract the Jacobian from +- `m` -- Vector of TPSs to extract the Jacobian from, must be 1-based indexing - `include_params` -- (Optional) Extract partial derivatives wrt parameters. Default is false ### Output -- `result` -- Preallocated matrix to fill with the transpose of the Jacobian of `m` +- `result` -- Matrix to fill with the transpose of the Jacobian of `m`, must be 1-based indexing """ -function jacobiant!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(first(m).tpsa).d)) - n = desc.nv +function jacobiant!(result, m; include_params=false) + Base.require_one_based_indexing(result, m) + n = numvars(first(m)) if include_params - n += desc.np + n += numparams(first(m)) end - if size(result)[2] != n + if size(result) != (n, length(m)) error("Incorrect size for result") end for i=1:length(m) @@ -381,35 +481,34 @@ function jacobiant!(result::Matrix{<:Union{Float64,ComplexF64}}, m::Vector{<:Uni end """ - jacobiant(m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) + jacobiant(m; include_params=false) where {N,P,I} Extracts the first-order partial derivatives (evaluated at 0) from the Vector of TPSs, -as the transpose of the Jacobian. Because of Julia's column-major indexing vs. C's row-major, -this routine will be slightly faster than using `jacobian` if the transpose of the Jacobian is -needed. The partial derivatives wrt the parameters will also be extracted when the `include_params` -flag is set to `true`. Note that this function is not calculating anything - just extracting the -first-order monomial coefficients already in the TPSs. +as the transpose of the Jacobian. The partial derivatives wrt the parameters will also +be extracted when the `include_params` flag is set to `true`. Note that this function is +not calculating anything - just extracting the first-order monomial coefficients already +in the TPSs. ### Input -- `m` -- `Vector` of TPSs. to extract the Jacobian from +- `m` --`Vector of TPSs to extract the Jacobian from, must be 1-based indexing - `include_params` -- (Optional) Extract partial derivatives wrt parameters. Default is false ### Output - `Jt` -- Transpose of the Jacobian of `m` """ -function jacobiant(m::Vector{<:Union{TPS,ComplexTPS}}; include_params=false) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(first(m).tpsa).d)) - n = desc.nv +function jacobiant(m; include_params=false) + Base.require_one_based_indexing(m) + n = numvars(first(m)) if include_params - n += desc.np + n += numparams(first(m)) end - result = Matrix{numtype(first(m))}(undef, length(m), n) + result = Matrix{numtype(first(m))}(undef, n, length(m)) jacobiant!(result, m, include_params=include_params) return result end """ - hessian!(result::Matrix{<:Union{Float64,ComplexF64}},t::Union{TPS,ComplexTPS}; include_params=false) + hessian!(result,t::Union{TPS,ComplexTPS}; include_params=false) Extracts the second-order partial derivatives (evaluated at 0) from the TPS and fills the `result` matrix in-place. The partial derivatives wrt the parameters will @@ -422,9 +521,10 @@ in the TPS. - `include_params` -- (Optional) Extract partial derivatives wrt parameters. Default is false ### Output -- `result` -- Preallocated matrix to fill with the Hessian of the TPS +- `result` -- Matrix to fill with the Hessian of the TPS, must be 1-based indexing """ -function hessian!(result::Matrix{<:Union{Float64,ComplexF64}},t::Union{TPS,ComplexTPS}; include_params=false) +function hessian!(result,t::Union{TPS,ComplexTPS}; include_params=false) + Base.require_one_based_indexing(result) d = Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d) desc = unsafe_load(d) n = desc.nv @@ -440,7 +540,7 @@ function hessian!(result::Matrix{<:Union{Float64,ComplexF64}},t::Union{TPS,Compl error("Hessian undefined for TPSA with at least one variable/parameter of order < 2") end end - result[:] .= 0. + result .= 0. idx = Cint(desc.nv+desc.np) maxidx = Cint(floor(n*(n+1)/2))+n v = Ref{numtype(t)}() diff --git a/src/global.jl b/src/global.jl new file mode 100644 index 00000000..deae699f --- /dev/null +++ b/src/global.jl @@ -0,0 +1,47 @@ +const MAD_TPSA::String = :("libgtpsa") +const MAD_TPSA_DEFAULT::Cuchar = 255 +const MAD_TPSA_SAME::Cuchar = 254 +const MAD_DESC_CURR::Ptr{Desc} = C_NULL +const DESC_MAX_TMP::Int = 8 + +# Global non-constants (types MUST be specified) +desc_current::Descriptor = Descriptor(MAD_DESC_CURR) # Current Descriptor +show_eps::Float64 = 0.0 # Print epsilon +show_sparse::Bool = false # Use sparse monomial print +show_header::Bool = false # Print a header above each TPS + +""" + setGTPSA!(a::AbstractString, val) + +Function to set global variables in GTPSA. Options for `a` are: + +- `desc_current::Descriptor` -- defines the `Descriptor` to use when that information is not explicitly (or implicitly in a TPS copy constructor) available, e.g. when calling `TPS(a)` where `a` is not a TPS. This is set each time a new `Descriptor` is defined +- `show_eps::Float64` -- defines the value below which the absolute value of a monomial coefficient is NOT printed +- `show_sparse::Bool` -- specifies whether the sparse monomial format is used for printing. This is useful for GTPSAs containing a large number of variables and parameters +- `show_header::Bool` -- specifies whether or not to print the GTPSA `Descriptor` information above each TPS output +""" +function setGTPSA!(a::AbstractString, val) + a == "desc_current" && (return (GTPSA.desc_current = val)) + a == "show_eps" && (return (GTPSA.show_eps = val)) + a == "show_sparse" && (return (GTPSA.show_sparse = val)) + a == "show_header" && (return (GTPSA.show_header = val)) + error("Global variable \"$(a)\" does not exist!") +end + +""" + getGTPSA(a::AbstractString) + +Function to get global variables in GTPSA. Options for `a` are: + +- `desc_current::Descriptor` -- defines the `Descriptor` to use when that information is not explicitly (or implicitly in a TPS copy constructor) available, e.g. when calling `TPS(a)` where `a` is not a TPS. This is set each time a new `Descriptor` is defined +- `show_eps::Float64` -- defines the value below which the absolute value of a monomial coefficient is NOT printed +- `show_sparse::Bool` -- specifies whether the sparse monomial format is used for printing. This is useful for GTPSAs containing a large number of variables and parameters +- `show_header::Bool` -- specifies whether or not to print the GTPSA `Descriptor` information above each TPS output +""" +function getGTPSA(a::AbstractString) + a == "desc_current" && (return GTPSA.desc_current) + a == "show_eps" && (return GTPSA.show_eps) + a == "show_sparse" && (return GTPSA.show_sparse) + a == "show_header" && (return GTPSA.show_header) + error("Global variable \"$(a)\" does not exist!") +end \ No newline at end of file diff --git a/src/low.jl b/src/low.jl new file mode 100644 index 00000000..b9385f06 --- /dev/null +++ b/src/low.jl @@ -0,0 +1,6 @@ +# Low-level functions/structs and constants +const NAMSZ::Int = 16 +include("low_level/mono.jl") +include("low_level/desc.jl") +include("low_level/rtpsa.jl") +include("low_level/ctpsa.jl") \ No newline at end of file diff --git a/src/low_level/ctpsa.jl b/src/low_level/ctpsa.jl index 605dead5..9d870d70 100644 --- a/src/low_level/ctpsa.jl +++ b/src/low_level/ctpsa.jl @@ -3,25 +3,24 @@ This is a 1-to-1 struct for the C definition `ctpsa` (complex TPSA) in GTPSA. -### Fields -- `d::Ptr{Cvoid}` -- Pointer to `Desc` for this `CTPSA` -- `uid::Cint` -- Special user field for external use (and padding) -- `mo::Cuchar` -- max ord (allocated) +- `d::Ptr{Cvoid}` -- Ptr to tpsa descriptor - `lo::Cuchar` -- lowest used ord - `hi::Cuchar` -- highest used ord -- `nz::Culonglong` -- zero/nonzero homogenous polynomials. Note: Int64 if 64 bit compiled C code, else 32 bit -- `nam::NTuple{NAMSZ,Cuchar}` -- tpsa name max string length 16 NAMSZ +- `mo::Cuchar` -- max ord +- `ao::Cuchar` -- allocated order +- `uid::Cint` -- Special user field for external use (and padding) +- `nam::NTuple{NAMSZ,Cuchar}` -- ctpsa name max string length 15 chars NAMSZ - `coef::Ptr{ComplexF64}` -- warning: must be identical to ctpsa up to coef excluded """ struct CTPSA - d::Ptr{Cvoid} - uid::Cint - mo::Cuchar - lo::Cuchar - hi::Cuchar - nz::Culonglong - nam::NTuple{NAMSZ,Cuchar} - coef::Ptr{ComplexF64} + d::Ptr{Cvoid} + lo::Cuchar + hi::Cuchar + mo::Cuchar + ao::Cuchar + uid::Cint + nam::NTuple{NAMSZ,Cuchar} + coef::Ptr{ComplexF64} end """ @@ -127,6 +126,24 @@ function mad_ctpsa_len(t::Ptr{CTPSA})::Cint return ret end +""" + mad_ctpsa_mo!(t::Ptr{CTPSA}, mo_::Cuchar)::Cuchar + +Sets the maximum order `mo` of the TPSA `t`, and returns the original `mo`. +`mo_` should be less than or equal to the allocated order `ao`. + +### Input +- `t` -- TPSA +- `mo_` -- Maximum order to set the TPSA + +### Output +- `ret` -- Original `mo` of the TPSA +""" +function mad_ctpsa_mo!(t::Ptr{CTPSA}, mo_::Cuchar)::Cuchar + ret = @ccall MAD_TPSA.mad_ctpsa_mo(t::Ptr{CTPSA}, mo_::Cuchar)::Cuchar + return ret +end + """ mad_ctpsa_nam(t::Ptr{CTPSA}, nam_::Cstring)::Cstring @@ -253,7 +270,11 @@ end """ mad_ctpsa_clrord!(t::Ptr{CTPSA}, ord::Cuchar) - ??? +Clears all monomial coefficients of the TPSA at order `ord` + +### Input +- `t` -- TPSA +- `ord` -- Order to clear monomial coefficients """ function mad_ctpsa_clrord!(t::Ptr{CTPSA}, ord::Cuchar) @ccall MAD_TPSA.mad_ctpsa_clrord(t::Ptr{CTPSA}, ord::Cuchar)::Cvoid @@ -378,12 +399,12 @@ function mad_ctpsa_setval!(t::Ptr{CTPSA}, v::ComplexF64) end """ - mad_ctpsa_update!(t::Ptr{CTPSA}, eps_::Cdouble) + mad_ctpsa_update!(t::Ptr{CTPSA}) ??? """ -function mad_ctpsa_update!(t::Ptr{CTPSA}, eps_::Cdouble) - ret = @ccall MAD_TPSA.mad_ctpsa_update(t::Ptr{CTPSA}, eps_::Cdouble)::Bool +function mad_ctpsa_update!(t::Ptr{CTPSA}) + @ccall MAD_TPSA.mad_ctpsa_update(t::Ptr{CTPSA})::Cvoid end """ @@ -664,23 +685,6 @@ function mad_ctpsa_cycle!(t::Ptr{CTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v end -""" - mad_ctpsa_get0(t::Ptr{CTPSA})::ComplexF64 - -Gets the 0th order (scalar) value of the TPSA - -### Input -- `t` -- TPSA - -### Output -- `ret` -- Scalar value of TPSA -""" -function mad_ctpsa_get0(t::Ptr{CTPSA})::ComplexF64 - ret = @ccall MAD_TPSA.mad_ctpsa_get0(t::Ptr{CTPSA})::ComplexF64 - return ret -end - - """ mad_ctpsa_geti(t::Ptr{CTPSA}, i::Cint)::ComplexF64 @@ -756,21 +760,6 @@ function mad_ctpsa_getsm(t::Ptr{CTPSA}, n::Cint, m::Vector{Cint})::ComplexF64 end -""" - mad_ctpsa_set0!(t::Ptr{CTPSA}, a::ComplexF64, b::ComplexF64) - -Sets the 0th order coefficient (scalar part of TPSA) according to `coef[0] = a*coef[0] + b`. Does not modify other values in TPSA. - -### Input -- `t` -- TPSA -- `a` -- Scaling of current 0th order value -- `b` -- Constant added to current 0th order value -""" -function mad_ctpsa_set0!(t::Ptr{CTPSA}, a::ComplexF64, b::ComplexF64) - @ccall MAD_TPSA.mad_ctpsa_set0(t::Ptr{CTPSA}, a::ComplexF64, b::ComplexF64)::Cvoid -end - - """ mad_ctpsa_seti!(t::Ptr{CTPSA}, i::Cint, a::ComplexF64, b::ComplexF64) @@ -820,19 +809,17 @@ function mad_ctpsa_setm!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}, a::ComplexF6 @ccall MAD_TPSA.mad_ctpsa_setm(t::Ptr{CTPSA}, n::Cint, m::Ptr{Cuchar}, a::ComplexF64, b::ComplexF64)::Cvoid end -""" - mad_ctpsa_cpy0!(t::Ptr{CTPSA}, r::Ptr{CTPSA}) - - ??? -""" -function mad_ctpsa_cpy0!(t::Ptr{CTPSA}, r::Ptr{CTPSA}) - @ccall MAD_TPSA.mad_ctpsa_cpy0(t::Ptr{CTPSA}, r::Ptr{CTPSA})::Cvoid -end """ mad_ctpsa_cpyi!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, i::Cint) - ??? +Copies the monomial coefficient at index `i` in `t` into the +same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `i` -- Index of monomial """ function mad_ctpsa_cpyi!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, i::Cint) @ccall MAD_TPSA.mad_ctpsa_cpyi(t::Ptr{CTPSA}, r::Ptr{CTPSA}, i::Cint)::Cvoid @@ -841,7 +828,14 @@ end """ mad_ctpsa_cpys!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, s::Cstring) - ??? +Copies the monomial coefficient at the monomial-as-string-of-order +`s` in `t` into the same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `n` -- Length of string +- `s` -- Monomial as string """ function mad_ctpsa_cpys!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, s::Cstring) @ccall MAD_TPSA.mad_ctpsa_cpys(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, s::Cstring)::Cvoid @@ -850,7 +844,14 @@ end """ mad_ctpsa_cpym!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}) - ??? +Copies the monomial coefficient at the monomial-as-vector-of-orders +`m` in `t` into the same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `n` -- Length of monomial `m` +- `m` -- Monomial as vector of orders """ function mad_ctpsa_cpym!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, m::Vector{Cuchar}) @ccall MAD_TPSA.mad_ctpsa_cpym(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, m::Ptr{Cuchar})::Cvoid @@ -859,7 +860,14 @@ end """ mad_ctpsa_cpysm!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, m::Vector{Cint}) - ??? +Copies the monomial coefficient at the monomial-as-sparse-monomial +`m` in `t` into the same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `n` -- Length of sparse monomial `m` +- `m` -- Monomial as sparse-monomial """ function mad_ctpsa_cpysm!(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, m::Vector{Cint}) @ccall MAD_TPSA.mad_ctpsa_cpysm(t::Ptr{CTPSA}, r::Ptr{CTPSA}, n::Cint, m::Ptr{Cint})::Cvoid @@ -884,22 +892,6 @@ end # Accessors without complex-by-value -""" - mad_ctpsa_get0_r!(t::Ptr{CTPSA}, r::Ref{ComplexF64}) - -Gets the 0th order (scalar) value of the TPSA in place. - -### Input -- `t` -- TPSA - -### Output -- `r` -- Scalar value of TPSA -""" -function mad_ctpsa_get0_r!(t::Ptr{CTPSA}, r::Ref{ComplexF64}) - ret = @ccall MAD_TPSA.mad_ctpsa_get0_r(t::Ptr{CTPSA}, r::Ptr{ComplexF64})::Cvoid - return ret -end - """ mad_ctpsa_geti_r!(t::Ptr{CTPSA}, i::Cint, r::Ref{ComplexF64}) @@ -976,24 +968,6 @@ function mad_ctpsa_getsm_r!(t::Ptr{CTPSA}, n::Cint, m::Vector{Cint}, r::Ref{Comp end -""" - mad_ctpsa_set0_r!(t::Ptr{CTPSA}, a_re::Cdouble, a_im::Cdouble, b_re::Cdouble, b_im::Cdouble) - -Sets the 0th order coefficient (scalar part of TPSA) according to `coef[0] = a*coef[0] + b`. Does not modify other values in TPSA. -Equivalent to `mad_ctpsa_set0` but without complex-by-value arguments. - -### Input -- `t` -- TPSA -- `a_re` -- Real part of `a` -- `a_im` -- Imaginary part of `a` -- `b_re` -- Real part of `b` -- `b_im` -- Imaginary part of `b` -""" -function mad_ctpsa_set0_r!(t::Ptr{CTPSA}, a_re::Cdouble, a_im::Cdouble, b_re::Cdouble, b_im::Cdouble) - @ccall MAD_TPSA.mad_ctpsa_set0_r(t::Ptr{CTPSA}, a_re::Cdouble, a_im::Cdouble, b_re::Cdouble, b_im::Cdouble)::Cvoid -end - - """ mad_ctpsa_seti_r!(t::Ptr{CTPSA}, i::Cint, a_re::Cdouble, a_im::Cdouble, b_re::Cdouble, b_im::Cdouble) @@ -1074,7 +1048,7 @@ end """ - mad_ctpsa_getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Vector{ComplexF64})::Cint + mad_ctpsa_getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v) Vectorized getter of the coefficients for monomials with indices `i..i+n`. Useful for extracting the 1st order parts of a TPSA to construct a matrix (`i = 1`, `n = nv+np = nn`). @@ -1086,11 +1060,9 @@ a TPSA to construct a matrix (`i = 1`, `n = nv+np = nn`). ### Output - `v` -- Array of coefficients for monomials `i..i+n` -- `ret` -- Copied length """ -function mad_ctpsa_getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Vector{ComplexF64})::Cint - ret = @ccall MAD_TPSA.mad_ctpsa_getv(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Ptr{ComplexF64})::Cint - return ret +function mad_ctpsa_getv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v) + @ccall MAD_TPSA.mad_ctpsa_getv(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Ptr{ComplexF64})::Cvoid end @@ -1105,13 +1077,9 @@ Vectorized setter of the coefficients for monomials with indices `i..i+n`. Usefu - `i` -- Starting index of monomials to set coefficients - `n` -- Number of monomials to set coefficients of starting at `i` - `v` -- Array of coefficients for monomials `i..i+n` - -### Output -- `ret` -- Copied length """ -function mad_ctpsa_setv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Vector{ComplexF64})::Cint - ret = @ccall MAD_TPSA.mad_ctpsa_setv(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Ptr{ComplexF64})::Cint - return ret +function mad_ctpsa_setv!(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Vector{ComplexF64}) + @ccall MAD_TPSA.mad_ctpsa_setv(t::Ptr{CTPSA}, i::Cint, n::Cint, v::Ptr{ComplexF64})::Cvoid end @@ -2719,7 +2687,16 @@ end """ mad_ctpsa_mord(na::Cint, ma::Vector{Ptr{CTPSA}}, hi::Bool)::Cuchar - ??? +If `hi` is false, getting the maximum `mo` among all TPSAs in `ma`. +If `hi` is `true`, gets the maximum `hi` of the map instead of `mo` + +### Input +- `na` -- Length of map `ma` +- `ma` -- Map (vector of TPSAs) +- `hi` -- If `true`, returns maximum `hi`, else returns maximum `mo` of the map + +### Output +- `ret` -- Maximum `hi` of the map if `hi` is `true`, else returns maximum `mo` of the map """ function mad_ctpsa_mord(na::Cint, ma::Vector{Ptr{CTPSA}}, hi::Bool)::Cuchar ret = @ccall MAD_TPSA.mad_ctpsa_mord(na::Cint, ma::Ptr{Ptr{CTPSA}}, hi::Bool)::Cuchar @@ -2935,7 +2912,7 @@ end """ - mad_ctpsa_debug(t::Ptr{CTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid}) + mad_ctpsa_debug(t::Ptr{CTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cint Prints TPSA with all information of data structure. @@ -2945,9 +2922,29 @@ Prints TPSA with all information of data structure. - `fnam_` -- (Optional) File name to print to - `line_` -- (Optional) Line number in file to start at - `stream_` -- (Optional) I/O stream to print to, default is `stdout` + +### Output +- `ret` -- ?? +""" +function mad_ctpsa_debug(t::Ptr{CTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cint + ret = @ccall MAD_TPSA.mad_ctpsa_debug(t::Ptr{CTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cint + return ret +end + +""" + mad_ctpsa_isval(t::Ptr{CTPSA})::Bool + +Sanity check of the TPSA integrity. + +### Input +- `t` -- TPSA to check if valid + +### Output +- `ret` -- True if valid TPSA, false otherwise """ -function mad_ctpsa_debug(t::Ptr{CTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid}) - @ccall MAD_TPSA.mad_ctpsa_debug(t::Ptr{CTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cvoid +function mad_ctpsa_isval(t::Ptr{CTPSA})::Bool + ret = @ccall MAD_TPSA.mad_ctpsa_isval(t::Ptr{CTPSA})::Bool + return ret end """ @@ -2967,6 +2964,17 @@ function mad_ctpsa_isvalid(t::Ptr{CTPSA})::Bool end +""" + mad_ctpsa_density(t::Ptr{CTPSA}, eps::Cdouble)::Cdouble + +??? +""" +function mad_ctpsa_density(t::Ptr{CTPSA}, eps::Cdouble)::Cdouble + ret = @ccall MAD_TPSA.mad_ctpsa_density(t::Ptr{CTPSA}, eps::Cdouble)::Cdouble + return ret +end + + """ mad_ctpsa_init(t::Ptr{CTPSA}, d::Ptr{Desc}, mo::Cuchar)::Ptr{CTPSA} diff --git a/src/low_level/desc.jl b/src/low_level/desc.jl index 8f13fbcd..6131e7ce 100644 --- a/src/low_level/desc.jl +++ b/src/low_level/desc.jl @@ -11,25 +11,30 @@ the monomials, monomial indexing function, and pre-allocated permanent temporari - `nv::Cint` -- Number of variables - `np::Cint` -- Number of parameters - `mo::Cuchar` -- Max order of both variables AND parameters -- `po::Cuchar` -- Max order of parameterss -- `to::Cuchar` -- Global order of truncation. Note: `ord_t` in gtpsa is `typedef` for `unsigned char` (`Cuchar`) +- `po::Cuchar` -- Max order of parameters - `no::Ptr{Cuchar}` -- Array of orders of each variable (first `nv` entries) and parameters (last `np` entries), length `nn`. Note: In C this is `const` + - `uno::Cint` -- User provided array of orders of each variable/parameter (with `mad_desc_newvpo`) - `nth::Cint` -- Max number of threads or 1 - `nc::Cuint` -- Number of coefficients (max length of TPSA) + +- `shared::Ptr{Cint}` -- counter of shared desc (all tables below except prms) - `monos::Ptr{Cuchar}` -- 'Matrix' storing the monomials (sorted by variable) - `ords::Ptr{Cuchar}` -- Order of each monomial of `To` - `prms::Ptr{Cuchar}` -- Order of parameters in each monomial of `To` (zero = no parameters) - `To::Ptr{Ptr{Cuchar}}` -- Table by orders - pointers to monomials, sorted by order - `Tv::Ptr{Ptr{Cuchar}}` -- Table by vars - pointers to monomials, sorted by variable - `ocs::Ptr{Ptr{Cuchar}}` -- `ocs[t,i]` -> `o` in mul, compute `o` on thread `t 3 <= o <= mo` aterminated with 0 + - `ord2idx::Ptr{Cint}` -- Order to polynomial start index in `To` (i.e. in TPSA `coef`) - `tv2to::Ptr{Cint}` -- Lookup `tv`->`to` - `to2tv::Ptr{Cint}` -- Lookup `to`->`tv` - `H::Ptr{Cint}` -- Indexing matrix in `Tv` - `L::Ptr{Ptr{Cint}}` -- Multiplication indexes `L[oa,ob]`->`L_ord` `L_ord[ia,ib]`->`ic` - `L_idx::Ptr{Ptr{Ptr{Cint}}}` -- `L_idx[oa,ob]`->`[start] [split] [end]` idxs in `L` + - `size::Culonglong` -- Bytes used by `desc`. `Unsigned Long Int`: In 32 bit system is `Int32` but 64 bit is `Int64`. Using `Culonglong` assuming 64 bit + - `t::Ptr{Ptr{Cvoid}}` -- Temporary array contains 8 pointers to `RTPSA`s already initialized - `ct::Ptr{Ptr{Cvoid}}` -- Temporary array contains 8 pointers to `CTPSA`s already initialized - `ti::Ptr{Cint}` -- idx of tmp used by each thread (length = # threads) @@ -42,13 +47,13 @@ struct Desc np::Cint mo::Cuchar po::Cuchar - to::Cuchar no::Ptr{Cuchar} uno::Cint nth::Cint nc::Cuint + shared::Ptr{Cint} monos::Ptr{Cuchar} ords::Ptr{Cuchar} prms::Ptr{Cuchar} @@ -204,24 +209,6 @@ function mad_desc_maxlen(d::Ptr{Desc}, mo::Cuchar)::Cint end -""" - mad_desc_gtrunc!(d::Ptr{Desc}, to::Cuchar)::Cuchar - -Sets the global truncation order `to` of the TPSA, and returns the old global truncation order. - -### Input -- `d` -- Descriptor -- `to` -- New global truncation order - -### Output -- `oldto` -- Old global truncation order -""" -function mad_desc_gtrunc!(d::Ptr{Desc}, to::Cuchar)::Cuchar - oldto = @ccall MAD_TPSA.mad_desc_gtrunc(d::Ptr{Desc}, to::Cuchar)::Cuchar - return oldto -end - - """ mad_desc_isvalids(d::Ptr{Desc}, n::Cint, s::Cstring)::Bool diff --git a/src/low_level/mono.jl b/src/low_level/mono.jl index 06adb358..4211fc5c 100644 --- a/src/low_level/mono.jl +++ b/src/low_level/mono.jl @@ -163,6 +163,17 @@ function mad_mono_ordpf(n::Cint, a::Vector{Cuchar}, stp::Cint)::Cdouble end +""" + mad_mono_eqn(n::Cint, a::Vector{Cuchar}, b::Cuchar)::Bool + +??? +""" +function mad_mono_eqn(n::Cint, a::Vector{Cuchar}, b::Cuchar)::Bool + ret = @ccall MAD_TPSA.mad_mono_eqn(n::Cint, a::Ptr{Cuchar}, b::Cuchar)::Bool + return ret +end + + """ mad_mono_eq(n::Cint, a::Vector{Cuchar}, b::Vector{Cuchar})::Bool diff --git a/src/low_level/rtpsa.jl b/src/low_level/rtpsa.jl index 3e677abf..b64bdf3d 100644 --- a/src/low_level/rtpsa.jl +++ b/src/low_level/rtpsa.jl @@ -5,21 +5,21 @@ This is a 1-to-1 struct for the C definition `tpsa` (real TPSA) in GTPSA. ### Fields - `d::Ptr{Cvoid}` -- Ptr to tpsa descriptor -- `uid::Cint` -- Special user field for external use (and padding) -- `mo::Cuchar` -- max ord (allocated) - `lo::Cuchar` -- lowest used ord - `hi::Cuchar` -- highest used ord -- `nz::Culonglong` -- zero/nonzero homogenous polynomials. Note: Int64 if 64 bit compiled C code, else 32 bit -- `nam::NTuple{NAMSZ,Cuchar}` -- tpsa name max string length 16 NAMSZ +- `mo::Cuchar` -- max ord +- `ao::Cuchar` -- allocated order +- `uid::Cint` -- Special user field for external use (and padding) +- `nam::NTuple{NAMSZ,Cuchar}` -- tpsa name max string length 15 chars NAMSZ - `coef::Ptr{Cdouble}` -- warning: must be identical to ctpsa up to coef excluded """ struct RTPSA - d::Ptr{Cvoid} - uid::Cint - mo::Cuchar + d::Ptr{Cvoid} lo::Cuchar - hi::Cuchar - nz::Culonglong + hi::Cuchar + mo::Cuchar + ao::Cuchar + uid::Cint nam::NTuple{NAMSZ,Cuchar} coef::Ptr{Cdouble} end @@ -128,6 +128,25 @@ function mad_tpsa_len(t::Ptr{RTPSA})::Cint end +""" + mad_tpsa_mo!(t::Ptr{RTPSA}, mo_::Cuchar)::Cuchar + +Sets the maximum order `mo` of the TPSA `t`, and returns the original `mo`. +`mo_` should be less than or equal to the allocated order `ao`. + +### Input +- `t` -- TPSA +- `mo_` -- Maximum order to set the TPSA + +### Output +- `ret` -- Original `mo` of the TPSA +""" +function mad_tpsa_mo!(t::Ptr{RTPSA}, mo_::Cuchar)::Cuchar + ret = @ccall MAD_TPSA.mad_tpsa_mo(t::Ptr{RTPSA}, mo_::Cuchar)::Cuchar + return ret +end + + """ mad_tpsa_nam(t::Ptr{RTPSA}, nam_::Cstring)::Cstring @@ -254,7 +273,11 @@ end """ mad_tpsa_clrord!(t::Ptr{RTPSA}, ord::Cuchar) - ??? +Clears all monomial coefficients of the TPSA at order `ord` + +### Input +- `t` -- TPSA +- `ord` -- Order to clear monomial coefficients """ function mad_tpsa_clrord!(t::Ptr{RTPSA}, ord::Cuchar) @ccall MAD_TPSA.mad_tpsa_clrord(t::Ptr{RTPSA}, ord::Cuchar)::Cvoid @@ -345,12 +368,12 @@ function mad_tpsa_setval!(t::Ptr{RTPSA}, v::Cdouble) end """ - mad_tpsa_update!(t::Ptr{RTPSA}, eps_::Cdouble) + mad_tpsa_update!(t::Ptr{RTPSA}) ??? """ -function mad_tpsa_update!(t::Ptr{RTPSA}, eps_::Cdouble) - ret = @ccall MAD_TPSA.mad_tpsa_update(t::Ptr{RTPSA}, eps_::Cdouble)::Bool +function mad_tpsa_update!(t::Ptr{RTPSA}) + @ccall MAD_TPSA.mad_tpsa_update(t::Ptr{RTPSA})::Cvoid end @@ -489,23 +512,6 @@ function mad_tpsa_cycle!(t::Ptr{RTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_ end -""" - mad_tpsa_get0(t::Ptr{RTPSA})::Cdouble - -Gets the 0th order (scalar) value of the TPSA - -### Input -- `t` -- TPSA - -### Output -- `ret` -- Scalar value of TPSA -""" -function mad_tpsa_get0(t::Ptr{RTPSA})::Cdouble - ret = @ccall MAD_TPSA.mad_tpsa_get0(t::Ptr{RTPSA})::Cdouble - return ret -end - - """ mad_tpsa_geti(t::Ptr{RTPSA}, i::Cint)::Cdouble @@ -581,20 +587,6 @@ function mad_tpsa_getsm(t::Ptr{RTPSA}, n::Cint, m::Vector{Cint})::Cdouble end -""" - mad_tpsa_set0!(t::Ptr{RTPSA}, a::Cdouble, b::Cdouble) - -Sets the 0th order coefficient (scalar part of TPSA) according to `coef[0] = a*coef[0] + b`. Does not modify other values in TPSA. - -### Input -- `t` -- TPSA -- `a` -- Scaling of current 0th order value -- `b` -- Constant added to current 0th order value -""" -function mad_tpsa_set0!(t::Ptr{RTPSA}, a::Cdouble, b::Cdouble) - @ccall MAD_TPSA.mad_tpsa_set0(t::Ptr{RTPSA}, a::Cdouble, b::Cdouble)::Cvoid -end - """ mad_tpsa_seti!(t::Ptr{RTPSA}, i::Cint, a::Cdouble, b::Cdouble) @@ -662,19 +654,17 @@ function mad_tpsa_setsm!(t::Ptr{RTPSA}, n::Cint, m::Vector{Cint}, a::Cdouble, b: @ccall MAD_TPSA.mad_tpsa_setsm(t::Ptr{RTPSA}, n::Cint, m::Ptr{Cint}, a::Cdouble, b::Cdouble)::Cvoid end -""" - mad_tpsa_cpy0!(t::Ptr{RTPSA}, r::Ptr{RTPSA}) - - ??? -""" -function mad_tpsa_cpy0!(t::Ptr{RTPSA}, r::Ptr{RTPSA}) - @ccall MAD_TPSA.mad_tpsa_cpy0(t::Ptr{RTPSA}, r::Ptr{RTPSA})::Cvoid -end """ mad_tpsa_cpyi!(t::Ptr{RTPSA}, r::Ptr{RTPSA}, i::Cint) - ??? +Copies the monomial coefficient at index `i` in `t` into the +same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `i` -- Index of monomial """ function mad_tpsa_cpyi!(t::Ptr{RTPSA}, r::Ptr{RTPSA}, i::Cint) @ccall MAD_TPSA.mad_tpsa_cpyi(t::Ptr{RTPSA}, r::Ptr{RTPSA}, i::Cint)::Cvoid @@ -683,7 +673,14 @@ end """ mad_tpsa_cpys!(t::Ptr{RTPSA}, r::Ptr{RTPSA}, n::Cint, s::Cstring) - ??? +Copies the monomial coefficient at the monomial-as-string-of-order +`s` in `t` into the same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `n` -- Length of string +- `s` -- Monomial as string """ function mad_tpsa_cpys!(t::Ptr{RTPSA}, r::Ptr{RTPSA}, n::Cint, s::Cstring) @ccall MAD_TPSA.mad_tpsa_cpys(t::Ptr{RTPSA}, r::Ptr{RTPSA}, n::Cint, s::Cstring)::Cvoid @@ -692,7 +689,14 @@ end """ mad_tpsa_cpym!(t::Ptr{RTPSA}, r::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}) - ??? +Copies the monomial coefficient at the monomial-as-vector-of-orders +`m` in `t` into the same monomial coefficient in `r` + +### Input +- `t` -- Source TPSA +- `r` -- Destination TPSA +- `n` -- Length of monomial `m` +- `m` -- Monomial as vector of orders """ function mad_tpsa_cpym!(t::Ptr{RTPSA}, r::Ptr{RTPSA}, n::Cint, m::Vector{Cuchar}) @ccall MAD_TPSA.mad_tpsa_cpym(t::Ptr{RTPSA}, r::Ptr{RTPSA}, n::Cint, m::Ptr{Cuchar})::Cvoid @@ -709,7 +713,8 @@ end """ - mad_tpsa_getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Vector{Cdouble})::Cint + mad_tpsa_getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v) + Vectorized getter of the coefficients for monomials with indices `i..i+n`. Useful for extracting the 1st order parts of a TPSA to construct a matrix (`i = 1`, `n = nv+np = nn`). @@ -721,15 +726,12 @@ a TPSA to construct a matrix (`i = 1`, `n = nv+np = nn`). ### Output - `v` -- Array of coefficients for monomials `i..i+n` -- `ret` -- Copied length """ -function mad_tpsa_getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v)::Cint - ret = @ccall MAD_TPSA.mad_tpsa_getv(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Ptr{Cdouble})::Cint - return ret +function mad_tpsa_getv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v) + @ccall MAD_TPSA.mad_tpsa_getv(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Ptr{Cdouble})::Cvoid end - """ mad_tpsa_setv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Vector{Cdouble}) @@ -740,13 +742,9 @@ Vectorized setter of the coefficients for monomials with indices `i..i+n`. Usefu - `i` -- Starting index of monomials to set coefficients - `n` -- Number of monomials to set coefficients of starting at `i` - `v` -- Array of coefficients for monomials `i..i+n` - -### Output -- `ret` -- Copied length """ function mad_tpsa_setv!(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Vector{Cdouble}) - ret = @ccall MAD_TPSA.mad_tpsa_setv(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Ptr{Cdouble})::Cint - return ret + @ccall MAD_TPSA.mad_tpsa_setv(t::Ptr{RTPSA}, i::Cint, n::Cint, v::Ptr{Cdouble})::Cvoid end @@ -1891,7 +1889,16 @@ end """ mad_tpsa_mord(na::Cint, ma::Vector{Ptr{RTPSA}}, hi::Bool)::Cuchar - ??? +If `hi` is false, getting the maximum `mo` among all TPSAs in `ma`. +If `hi` is `true`, gets the maximum `hi` of the map instead of `mo` + +### Input +- `na` -- Length of map `ma` +- `ma` -- Map (vector of TPSAs) +- `hi` -- If `true`, returns maximum `hi`, else returns maximum `mo` of the map + +### Output +- `ret` -- Maximum `hi` of the map if `hi` is `true`, else returns maximum `mo` of the map """ function mad_tpsa_mord(na::Cint, ma::Vector{Ptr{RTPSA}}, hi::Bool)::Cuchar ret = @ccall MAD_TPSA.mad_tpsa_mord(na::Cint, ma::Ptr{Ptr{RTPSA}}, hi::Bool)::Cuchar @@ -2107,7 +2114,7 @@ end """ - mad_tpsa_debug(t::Ptr{RTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid}) + mad_tpsa_debug(t::Ptr{RTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cint Prints TPSA with all information of data structure. @@ -2117,9 +2124,48 @@ Prints TPSA with all information of data structure. - `fnam_` -- (Optional) File name to print to - `line_` -- (Optional) Line number in file to start at - `stream_` -- (Optional) I/O stream to print to, default is `stdout` + +### Output +- `ret` -- ?? +""" +function mad_tpsa_debug(t::Ptr{RTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cint + ret = @ccall MAD_TPSA.mad_tpsa_debug(t::Ptr{RTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cint + return ret +end + + +""" + mad_tpsa_prtdensity(stream_::Ptr{Cvoid}) + +??? +""" +function mad_tpsa_prtdensity(stream_::Ptr{Cvoid}) + @ccall MAD_TPSA.mad_tpsa_prtdensity(stream_::Ptr{Cvoid})::Cvoid +end + +""" + mad_tpsa_clrdensity!()::Cvoid + +??? +""" +function mad_tpsa_clrdensity!()::Cvoid + @ccall MAD_TPSA.mad_tpsa_clrdensity()::Cvoid +end + +""" + mad_tpsa_isval(t::Ptr{RTPSA})::Bool + +Sanity check of the TPSA integrity. + +### Input +- `t` -- TPSA to check if valid + +### Output +- `ret` -- True if valid TPSA, false otherwise """ -function mad_tpsa_debug(t::Ptr{RTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid}) - @ccall MAD_TPSA.mad_tpsa_debug(t::Ptr{RTPSA}, name_::Cstring, fnam_::Cstring, line_::Cint, stream_::Ptr{Cvoid})::Cvoid +function mad_tpsa_isval(t::Ptr{RTPSA})::Bool + ret = @ccall MAD_TPSA.mad_tpsa_isval(t::Ptr{RTPSA})::Bool + return ret end """ @@ -2139,6 +2185,17 @@ function mad_tpsa_isvalid(t::Ptr{RTPSA})::Bool end +""" + mad_tpsa_density(t::Ptr{RTPSA}, eps::Cdouble)::Cdouble + +??? +""" +function mad_tpsa_density(t::Ptr{RTPSA}, eps::Cdouble)::Cdouble + ret = @ccall MAD_TPSA.mad_tpsa_density(t::Ptr{RTPSA}, eps::Cdouble)::Cdouble + return ret +end + + """ mad_tpsa_init(t::Ptr{RTPSA}, d::Ptr{Desc}, mo::Cuchar)::Ptr{RTPSA} @@ -2156,4 +2213,5 @@ the maximum order of the descriptor. `t` is modified in place and also returned. function mad_tpsa_init!(t::Ptr{RTPSA}, d::Ptr{Desc}, mo::Cuchar)::Ptr{RTPSA} t = @ccall MAD_TPSA.mad_tpsa_init(t::Ptr{RTPSA}, d::Ptr{Desc}, mo::Cuchar)::Ptr{RTPSA} return t -end \ No newline at end of file +end + diff --git a/src/methods.jl b/src/methods.jl index 74a0642e..203e7735 100644 --- a/src/methods.jl +++ b/src/methods.jl @@ -1,53 +1,61 @@ -# --- Evaluate --- -# TPS: +# --- clear --- +clear!(t::Ptr{RTPSA}) = mad_tpsa_clear!(t) +clear!(t::Ptr{CTPSA}) = mad_ctpsa_clear!(t) + """ - evaluate(m::Vector{TPS}, x::Vector{<:Real})::Vector{Float64} + clear!(t::Union{TPS,ComplexTPS}) -Evaluates `m` at the point `x`. +Clears the TPS (sets all monomial coefficients to 0). """ -function evaluate(m::Vector{TPS}, x::Vector{<:Real})::Vector{Float64} - na = Cint(length(m)) - ma = map(t->t.tpsa, m) - nb = Cint(length(x)) - tb = convert(Vector{Float64}, x) - tc = Vector{Float64}(undef, nb) - mad_tpsa_eval!(na, ma, nb, tb, tc) - return tc +function clear!(t::Union{TPS,ComplexTPS}) + clear!(t.tpsa) end +# --- complex! --- + """ - evaluate(t1::TPS, x::Vector{<:Real})::Float64 + complex!(ct::ComplexTPS, t::TPS) -Evaluates `t1` at the point `x`. +Sets the pre-allocated `ComplexTPS` `ct` equal to `t`. """ -function evaluate(t1::TPS, x::Vector{<:Real})::Float64 - return evaluate([t1], x)[1] +function complex!(ct::ComplexTPS, t::TPS) + mad_ctpsa_cplx!(t.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ct.tpsa) end +# --- Evaluate --- +eval!(na::Cint, ma::Vector{Ptr{RTPSA}}, nb::Cint, tb::Vector{Float64}, tc::Vector{Float64}) = mad_tpsa_eval!(na, ma, nb, tb, tc) +eval!(na::Cint, ma::Vector{Ptr{CTPSA}}, nb::Cint, tb::Vector{ComplexF64}, tc::Vector{ComplexF64}) = mad_ctpsa_eval!(na, ma, nb, tb, tc) -# ComplexTPS: """ - evaluate(m::Vector{ComplexTPS}, x::Vector{<:Number})::Vector{ComplexF64} + evaluate!(tc::Vector{<:Number}, m::Vector{T}, tb::Vector{<:Number}; work_low::Vector{<:Union{Ptr{RTPSA},Ptr{CTPSA}}}=Vector{lowtype(T)}(undef, length(m))) where {T<:Union{TPS,ComplexTPS}} -Evaluates `m` at the point `x`. +Evaluates the vector function `m` at the point `tb`, and fills `tc` with the result. +An optional container `work_low` can be provided for containing the low-level TPS +structs for zero allocations. """ -function evaluate(m::Vector{ComplexTPS}, x::Vector{<:Number})::Vector{ComplexF64} +function evaluate!(tc::Vector{<:Number}, m::Vector{T}, tb::Vector{<:Number}; work_low::Vector{<:Union{Ptr{RTPSA},Ptr{CTPSA}}}=Vector{lowtype(T)}(undef, length(m))) where {T<:Union{TPS,ComplexTPS}} na = Cint(length(m)) - ma = map(t->t.tpsa, m) - nb = Cint(length(x)) - tb = convert(Vector{ComplexF64}, x) - tc = Vector{ComplexF64}(undef, nb) - mad_ctpsa_eval!(na, ma, nb, tb, tc) - return tc + nb = Cint(length(tb)) + @assert na == nb "Vector lengths for TPSs and evaluation point disagree" + @assert length(tc) == nb "Output vector length disagrees with input vector length" + @assert length(work_low) == na "work_low vector length != input vector length" + @assert eltype(tc) == numtype(T) "Output vector eltype should be $(numtype(T)), received $(typeof(tc))" + + map!(t->t.tpsa, work_low, m) + eval!(na, work_low, nb, tb, tc) + return end """ - evaluate(ct1::ComplexTPS, x::Vector{<:Number})::ComplexF64 + evaluate(m::Vector{T}, tb::Vector{<:Number}) where {T<:Union{TPS,ComplexTPS}} -Evaluates `ct1` at the point `x`. +Evaluates the vector function `m` at the point `tb`. """ -function evaluate(ct1::ComplexTPS, x::Vector{<:Number})::ComplexF64 - return evaluate([ct1], x)[1] +function evaluate(m::Vector{T}, tb::Vector{<:Number}) where {T<:Union{TPS,ComplexTPS}} + na = Cint(length(m)) + tc = Vector{numtype(T)}(undef, na) + evaluate!(tc, m, tb) + return tc end # --- Integral --- @@ -55,6 +63,21 @@ end integ!(tpsa1::Ptr{RTPSA}, tpsa::Ptr{RTPSA}, var::Cint) = (@inline; mad_tpsa_integ!(tpsa1, tpsa, var)) integ!(ctpsa1::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, var::Cint) = (@inline; mad_ctpsa_integ!(ctpsa1, ctpsa, var)) +""" + integ!(t::T, t1::T, var::Integer=1) where {T<:Union{TPS,ComplexTPS}} + ∫!(t::T, t1::T, var::Integer=1) where {T<:Union{TPS,ComplexTPS}} + +Integrates `t1` wrt the variable `var` and fills `t` with the result. +Integration wrt parameters is not allowed, and integration wrt higher order +monomials is not currently supported. +""" +function integ!(t::T, t1::T, var::Integer=1) where {T<:Union{TPS,ComplexTPS}} + integ(t1.tpsa, t.tpsa, Cint(var)) + return +end + +∫! = integ! + """ integ(t1::Union{TPS, ComplexTPS}, var::Integer=1) ∫(t1::Union{TPS, ComplexTPS}, var::Integer=1) @@ -65,7 +88,7 @@ monomials is not currently supported. """ function integ(t1::Union{TPS, ComplexTPS}, var::Integer=1) t = zero(t1) - integ!(t1.tpsa, t.tpsa, Cint(var)) + integ!(t, t1, var) return t end @@ -79,16 +102,35 @@ derivm!(tpsa1::Ptr{RTPSA}, tpsa::Ptr{RTPSA}, n::Cint, ords::Vector{Cuchar}) = (@ derivm!(ctpsa1::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, n::Cint, ords::Vector{Cuchar}) = (@inline; mad_ctpsa_derivm!(ctpsa1, ctpsa, n, ords)) """ - deriv(t1::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) - ∂(t1::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) + deriv!(t::T, t1::T, v::Union{TPSIndexType, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) where {T<:Union{TPS,ComplexTPS}} + ∂!(t::T, t1::T, v::Union{TPSIndexType, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) where {T<:Union{TPS,ComplexTPS}} + +Differentiates `t1` wrt the variable/parameter specified by the variable/parameter index, or +alternatively any monomial specified by indexing-by-order OR indexing-by-sparse monomial, and +sets `t` equal to the result in-place. See the `deriv` documentation for examples. + +### Input +- `v` -- An integer (for variable index), vector/tuple of orders for each variable (for indexing-by-order), or vector/tuple of pairs (sparse monomial) +- `param` -- (Keyword argument, optional) An integer for the parameter index +- `params` -- (Keyword argument, optional) Vector/tuple of pairs for sparse-monomial indexing +""" +function deriv!(t::T, t1::T, v::Union{TPSIndexType, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) where {T<:Union{TPS,ComplexTPS}} + low_deriv!(t, t1, v, param, params) +end + +∂! = deriv! + +""" + deriv(t1::Union{TPS,ComplexTPS}, v::Union{TPSIndexType, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) + ∂(t1::Union{TPS,ComplexTPS}, v::Union{TPSIndexType, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) Differentiates `t1` wrt the variable/parameter specified by the variable/parameter index, or alternatively any monomial specified by indexing-by-order OR indexing-by-sparse monomial. ### Input -- `v` -- An integer (for variable index), an array of orders for each variable (for indexing-by-order), or an array of pairs (sparse monomial) +- `v` -- An integer (for variable index), vector/tuple of orders for each variable (for indexing-by-order), or vector/tuple of pairs (sparse monomial) - `param` -- (Keyword argument, optional) An integer for the parameter index -- `params` -- (Keyword argument, optional) An array of pairs for sparse-monomial indexing +- `params` -- (Keyword argument, optional) Vector/tuple of pairs for sparse-monomial indexing # Examples: Variable/Parameter Index: ```julia-repl @@ -148,75 +190,72 @@ TPS: 1.0000000000000000e+00 0 0 0 ``` """ -function deriv(t1::Union{TPS,ComplexTPS}, v::Union{Integer, Vector{<:Union{<:Pair{<:Integer,<:Integer},<:Integer}}, Nothing}=nothing; param::Union{<:Integer,Nothing}=nothing, params::Union{Vector{<:Pair{<:Integer,<:Integer}}, Nothing}=nothing) - return low_deriv(t1, v, param, params) +function deriv(t1::Union{TPS,ComplexTPS}, v::Union{TPSIndexType, Nothing}=nothing; param::Union{Integer,Nothing}=nothing, params::Union{SMIndexType, Nothing}=nothing) + t = zero(t1) + low_deriv!(t, t1, v, param, params) + return t end # Variable/parameter: -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Integer, param::Nothing, params::Nothing) - t = zero(t1) +function low_deriv!(t::T, t1::T, v::Integer, param::Nothing, params::Nothing) where {T<:Union{TPS,ComplexTPS}} deriv!(t1.tpsa, t.tpsa, convert(Cint, v)) - return t end -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Integer, params::Nothing) - t = zero(t1) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) - nv = desc.nv # TOTAL NUMBER OF VARS!!!! +function low_deriv!(t::T, t1::T, v::Nothing, param::Integer, params::Nothing) where {T<:Union{TPS,ComplexTPS}} + nv = numvars(t1) deriv!(t1.tpsa, t.tpsa, Cint(param)+nv) - return t end # Default to first variable if nothing passed: -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Nothing) - return low_deriv(t1, 1, nothing, nothing) +function low_deriv!(t::T, t1::T, v::Nothing, param::Nothing, params::Nothing) where {T<:Union{TPS,ComplexTPS}} + low_deriv!(t1, 1, nothing, nothing) end # Monomial by order: -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Vector{<:Integer}, param::Nothing, params::Nothing) - t = zero(t1) +function low_deriv!(t::T, t1::T, v::MIndexType, param::Nothing, params::Nothing) where {T<:Union{TPS,ComplexTPS}} derivm!(t1.tpsa, t.tpsa, Cint(length(v)), convert(Vector{Cuchar}, v)) - return t end # Monomial by sparse monomial: -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Vector{<:Pair{<:Integer,<:Integer}}, param::Nothing, params::Vector{<:Pair{<:Integer,<:Integer}}) - t = zero(t1) +function low_deriv!(t::T, t1::T, v::SMIndexType, param::Nothing, params::SMIndexType) where {T<:Union{TPS,ComplexTPS}} # Need to create array of orders with length nv + np ords, n = pairs_to_m(t1,v,params=params) derivm!(t1.tpsa, t.tpsa, n, ords) - return t end -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Vector{<:Pair{<:Integer,<:Integer}}, param::Nothing, params::Nothing) - t = zero(t1) +function low_deriv!(t::T, t1::T, v::SMIndexType, param::Nothing, params::Nothing) where {T<:Union{TPS,ComplexTPS}} # Need to create array of orders with length nv + np ords, n = pairs_to_m(t1,v) derivm!(t1.tpsa, t.tpsa, n, ords) - return t end -function low_deriv(t1::Union{TPS,ComplexTPS}, v::Nothing, param::Nothing, params::Vector{<:Pair{<:Integer,<:Integer}}) - t = zero(t1) +function low_deriv!(t::T, t1::T, v::Nothing, param::Nothing, params::SMIndexType) where {T<:Union{TPS,ComplexTPS}} # Need to create array of orders with length nv + np ords, n = pairs_to_m(t1,Pair{Int,Int}[],params=params) derivm!(t1.tpsa, t.tpsa, n, ords) - return t end # Throw error if no above use cases satisfied: -function low_deriv(t1::Union{TPS,ComplexTPS}, v, param, params) +function low_deriv(t::T, t1::T, v, param, params) where {T<:Union{TPS,ComplexTPS}} error("Invalid monomial specified. Please use ONE of variable/parameter index, index by order, or index by sparse monomial.") end ∂ = deriv -# --- getord and cutord --- +# --- getord --- # Low-level equivalent calls for TPS and ComplexTPS: getord!(tpsa1::Ptr{RTPSA}, tpsa::Ptr{RTPSA}, order::Cuchar) = (@inline; mad_tpsa_getord!(tpsa1, tpsa, order)) getord!(ctpsa1::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, order::Cuchar) = (@inline; mad_ctpsa_getord!(ctpsa1, ctpsa, order)) -cutord!(tpsa1::Ptr{RTPSA}, tpsa::Ptr{RTPSA}, order::Cint) = (@inline; mad_tpsa_cutord!(tpsa1, tpsa, order)) -cutord!(ctpsa1::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, order::Cint) = (@inline; mad_ctpsa_cutord!(ctpsa1, ctpsa, order)) + +""" + getord!(t::T, t1::T, order::Integer) where {T<:Union{TPS,ComplexTPS}} + +Extracts one homogenous polynomial from `t1` of the given order and +fills `t` with the result in-place. +""" +function getord!(t::T, t1::T, order::Integer) where {T<:Union{TPS,ComplexTPS}} + getord!(t1.tpsa, t.tpsa, Cuchar(order)) +end """ getord(t1::Union{TPS, ComplexTPS}, order::Integer) @@ -225,10 +264,25 @@ Extracts one homogenous polynomial from `t1` of the given order. """ function getord(t1::Union{TPS, ComplexTPS}, order::Integer) t = zero(t1) - getord!(t1.tpsa, t.tpsa, convert(Cuchar, order)) + getord!(t, t1, order) return t end +# --- cutord --- +cutord!(tpsa1::Ptr{RTPSA}, tpsa::Ptr{RTPSA}, order::Cint) = (@inline; mad_tpsa_cutord!(tpsa1, tpsa, order)) +cutord!(ctpsa1::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, order::Cint) = (@inline; mad_ctpsa_cutord!(ctpsa1, ctpsa, order)) + +""" + cutord!(t::T, t1::T, order::Integer) where {T<:Union{TPS,ComplexTPS}} + +Cuts out the monomials in `t1` at the given order and above. Or, if `order` +is negative, will cut monomials with orders at and below `abs(order)`. `t` +is filled in-place with the result. See the documentation for `cutord` for examples. +""" +function cutord!(t::T, t1::T, order::Integer) where {T<:Union{TPS,ComplexTPS}} + cutord!(t1.tpsa, t.tpsa, convert(Cint, order)) +end + """ cutord(t1::Union{TPS, ComplexTPS}, order::Integer) @@ -257,475 +311,227 @@ TPS: """ function cutord(t1::Union{TPS, ComplexTPS}, order::Integer) t = zero(t1) - cutord!(t1.tpsa, t.tpsa, convert(Cint, order)) + cutord!(t, t1, order) return t end - -# --- scalar --- +# --- clearord! --- +clrord!(t::Ptr{RTPSA}, ord::Cuchar) = mad_tpsa_clrord!(t, ord) +clrord!(t::Ptr{CTPSA}, ord::Cuchar) = mad_ctpsa_clrord!(t, ord) """ - scalar(t::Union{TPS,ComplexTPS}) + clearord!(t::Union{TPS,ComplexTPS}, order::Integer) -Extracts the scalar part of the TPS. Equivalent to `t[0]` but -this can be easily broadcasted. +Clears all monomial coefficients in `t` at order `order`. """ -function scalar(t::Union{TPS,ComplexTPS}) - return t[0] -end - - -# --- Poisson bracket --- -# Low-level calls -poisbra!(tpsa1::Ptr{RTPSA}, tpsa2::Ptr{RTPSA}, tpsa::Ptr{RTPSA}, nv::Cint) = (@inline; mad_tpsa_poisbra!(tpsa1, tpsa2, tpsa, nv)) -poisbra!(tpsa1::Ptr{RTPSA}, ctpsa1::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, nv::Cint) = (@inline; mad_ctpsa_poisbrat!(ctpsa1,tpsa1,ctpsa, nv)) -poisbra!(ctpsa1::Ptr{CTPSA}, tpsa1::Ptr{RTPSA}, ctpsa::Ptr{CTPSA}, nv::Cint) = (@inline; mad_ctpsa_tpoisbra!(tpsa1, ctpsa1, ctpsa, nv)) -poisbra!(ctpsa1::Ptr{CTPSA}, ctpsa2::Ptr{CTPSA}, ctpsa::Ptr{CTPSA}, nv::Cint) = (@inline; mad_ctpsa_poisbra!(ctpsa1,ctpsa2, ctpsa, nv)) +clearord!(t::Union{TPS,ComplexTPS}, order::Integer) = clrord!(t.tpsa, convert(Cuchar, order)) """ - pb(f::Union{TPS, ComplexTPS}, g::Union{TPS, ComplexTPS}) + clearord(t1::Union{TPS,ComplexTPS}, order::Integer) -Assuming the variables in the TPSA are canonically-conjugate, and ordered so that the canonically- -conjugate variables are consecutive (q₁, p₁, q₂, p₂, ...), computes the Poisson bracket -of the scalar functions `f` and `g`. The Poisson bracket of two functions `{f, g}` is defined as -`Σᵢ (∂f/∂qᵢ)(∂g/∂pᵢ) - (∂g/∂qᵢ)(∂f/∂pᵢ)`. - -# Examples -```julia-repl -julia> d = Descriptor(4,10); - -julia> x = vars(d); - -julia> f = (x[1]^2 + x[2]^2)/2 + (x[3]^2 + x[4]^2)/2; - -julia> pb(f,x[1]) -TPS: - Coefficient Order Exponent - -1.0000000000000000e+00 1 0 1 0 0 - - -julia> pb(f,x[2]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 1 0 0 0 - - -julia> pb(f,x[3]) -TPS: - Coefficient Order Exponent - -1.0000000000000000e+00 1 0 0 0 1 - - -julia> pb(f,x[4]) -TPS: - Coefficient Order Exponent - 1.0000000000000000e+00 1 0 0 1 0 -``` +Returns a new TPS equal to `t1` but with all monomial coefficients +at the given `order` cleared (set equal to 0). """ -function pb(f::Union{TPS, ComplexTPS}, g::Union{TPS, ComplexTPS}) - t = promote_type(typeof(f),typeof(g))(use=f) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(f.tpsa).d)) - poisbra!(f.tpsa,g.tpsa,t.tpsa, desc.nv) +function clearord(t1::Union{TPS,ComplexTPS}, order::Integer) + t = zero(t1) + copy!(t,t1) + clearord!(t,order) return t end -# --- Lie bracket --- -liebra!(na::Cint, m1::Vector{Ptr{RTPSA}}, m2::Vector{Ptr{RTPSA}}, m3::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_liebra!(na, m1, m2, m3)) -liebra!(na::Cint, m1::Vector{Ptr{CTPSA}}, m2::Vector{Ptr{CTPSA}}, m3::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_liebra!(na, m1, m2, m3)) +# --- scalar --- """ - lb(A::Vector{<:Union{TPS,ComplexTPS}}, F::Vector{<:Union{TPS,ComplexTPS}}) - -Computes the Lie bracket of the vector functions `A` and `F`, defined over N variables as -`Σᵢᴺ Aᵢ (∂F/∂xᵢ) - Fᵢ (∂A/∂xᵢ)` + scalar(t::Union{TPS,ComplexTPS}) -# Example -```julia-repl -julia> d = Descriptor(2,10); x = vars(); - -julia> A = [-x[2], x[1]] -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: -1.0000000000000000e+00 1 0 1 -------------------------------------------------- - 2: 1.0000000000000000e+00 1 1 0 - - -julia> F = [-x[1]^2, 2*x[1]*x[2]] -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: -1.0000000000000000e+00 2 2 0 -------------------------------------------------- - 2: 2.0000000000000000e+00 2 1 1 - - -julia> lb(A,F) -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: 4.0000000000000000e+00 2 1 1 -------------------------------------------------- - 2: 3.0000000000000000e+00 2 2 0 - 2: -2.0000000000000000e+00 2 0 2 -``` +Extracts the scalar part of the TPS. Equivalent to `t[0]` but +this can be easily broadcasted. """ -function lb(A::Vector{<:Union{TPS,ComplexTPS}}, F::Vector{<:Union{TPS,ComplexTPS}}) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(A[1].tpsa).d)) - if length(A) != desc.nv || length(F) != desc.nv - error("Vector length != number of variables in the GTPSA") - end - A1, F1 = promote(A, F) - m1 = map(t->t.tpsa, A1) - m2 = map(t->t.tpsa, F1) - mc = zero.(A1) - m3 = map(t->t.tpsa, mc) - GC.@preserve A1 F1 liebra!(Cint(length(A)), m1, m2, m3) - return mc +function scalar(t::Union{TPS,ComplexTPS}) + return t[0] end -# --- getvectorfield --- -vec2fld!(na::Cint, tpsa::Ptr{RTPSA}, m::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_vec2fld!(na, tpsa, m)) -vec2fld!(na::Cint, ctpsa::Ptr{CTPSA}, m::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_vec2fld!(na, ctpsa, m)) - -""" - getvectorfield(h::Union{TPS,ComplexTPS})::Vector{<:typeof(h)} - -Assuming the variables in the TPSA are canonically-conjugate, and ordered so that the canonically- -conjugate variables are consecutive (q₁, p₁, q₂, p₂, ...), calculates the vector field (Hamilton's -equations) from the passed Hamiltonian, defined as `[∂h/∂p₁, -∂h/∂q₁, ...]` - -# Example -```julia-repl -julia> d = Descriptor(2,10); x = vars(); - -julia> h = (x[1]^2 + x[2]^2)/2 -TPS: - Coefficient Order Exponent - 5.0000000000000000e-01 2 2 0 - 5.0000000000000000e-01 2 0 2 - - -julia> getvectorfield(h) -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: -1.0000000000000000e+00 1 0 1 -------------------------------------------------- - 2: 1.0000000000000000e+00 1 1 0 -``` -""" -function getvectorfield(h::Union{TPS,ComplexTPS})::Vector{<:typeof(h)} - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(h.tpsa).d)) - na = desc.nv - mc = Vector{typeof(h)}(undef, na) - for i in eachindex(mc) - mc[i] = zero(h) - end - m = map(t->t.tpsa, mc) - vec2fld!(na, h.tpsa, m) - return mc -end +# --- composition --- +compose!(na::Cint, ma::Vector{Ptr{RTPSA}}, nb::Cint, mb::Vector{Ptr{RTPSA}}, mc::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_compose!(na, ma, nb, mb, mc)) +compose!(na::Cint, ma::Vector{Ptr{CTPSA}}, nb::Cint, mb::Vector{Ptr{CTPSA}}, mc::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_compose!(na, ma, nb, mb, mc)) -# --- gethamiltonian --- -fld2vec!(na::Cint, ma::Vector{Ptr{RTPSA}}, tpsa::Ptr{RTPSA}) = (@inline; mad_tpsa_fld2vec!(na, ma, tpsa)) -fld2vec!(na::Cint, ma::Vector{Ptr{CTPSA}}, ctpsa::Ptr{CTPSA}) = (@inline; mad_ctpsa_fld2vec!(na, ma, ctpsa)) """ - gethamiltonian(F::Vector{<:Union{TPS,ComplexTPS}}) - -Assuming the variables in the TPSA are canonically-conjugate, and ordered so that the canonically- -conjugate variables are consecutive (q₁, p₁, q₂, p₂, ...), this function calculates the Hamiltonian -from a vector field `F` that can be obtained from a Hamiltonian (e.g. by `getvectorfield`). Explicitly, -`∫ F₁ dp₁ - ∫ F₂ dq₁ + ... + ∫ F₂ₙ₋₁ dpₙ - ∫ F₂ₙ dqₙ ` - -# Example -```julia-repl -julia> d = Descriptor(2,10); x = vars(); - -julia> h = (x[1]^2 + x[2]^2)/2 -TPS: - Coefficient Order Exponent - 5.0000000000000000e-01 2 2 0 - 5.0000000000000000e-01 2 0 2 + compose!(m::Vector{<:Union{TPS,ComplexTPS}}, m2::Vector{<:Union{TPS,ComplexTPS}}, m1::Vector{<:Union{TPS,ComplexTPS}}; work_low::Union{Nothing,Tuple{Vararg{Vector{<:Union{Ptr{RTPSA},Ptr{CTPSA}}}}}}=nothing, work_prom::Union{Nothing,Tuple{Vararg{Vector{<:ComplexTPS}}}}=nothing) +Composes the vector functions `m2 ∘ m1` and stores the result in-place in `m`. Promotion is allowed, provided +the output vector function `m` has the correct promoted type. -julia> F = getvectorfield(h) -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: -1.0000000000000000e+00 1 0 1 -------------------------------------------------- - 2: 1.0000000000000000e+00 1 1 0 +For all compositions, 3 temporary vectors must be generated that contain Ptr{RTPSA} or Ptr{CTPSA} +for each TPS in the map (depending on output type), to pass to the low-level C composition function in GTPSA. +They are correspondingly referred to as `outx_low`, `m2x_low`, and `m1x_low`. These three temporaries containers +can be optionally passed as a tuple in `work_low`, and must satisfy the following requirements: - -julia> gethamiltonian(F) -TPS: - Coefficient Order Exponent - 5.0000000000000000e-01 2 2 0 - 5.0000000000000000e-01 2 0 2 ``` -""" -function gethamiltonian(F::Vector{<:Union{TPS,ComplexTPS}}) - descF = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(F[1].tpsa).d)) - if length(F) != descF.nv - error("Vector length != number of variables in the GTPSA") - end - h = zero(F[1]) - m1 = map(t->t.tpsa, F) - fld2vec!(Cint(length(m)), m1, h.tpsa) - return h -end - - -# --- exp(F . grad) m --- -exppb!(na::Cint, ma::Vector{Ptr{RTPSA}}, mb::Vector{Ptr{RTPSA}}, mc::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_exppb!(na, ma, mb, mc)) -exppb!(na::Cint, ma::Vector{Ptr{CTPSA}}, mb::Vector{Ptr{CTPSA}}, mc::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_exppb!(na, ma, mb, mc)) - -""" - exppb(F::Vector{<:Union{TPS,ComplexTPS}}, m::Vector{<:Union{TPS,ComplexTPS}}=vars(first(F))) - -Calculates `exp(F⋅∇)m = m + F⋅∇m + (F⋅∇)²m/2! + ...`. If `m` is not provided, it is assumed -to be the identity. - -# Example - -```julia-repl -julia> d = Descriptor(2,10); x = vars()[1]; p = vars()[2]; - -julia> time = 0.01; k = 2; m = 0.01; - -julia> h = p^2/(2m) + 1/2*k*x^2; - -julia> hf = getvectorfield(h); - -julia> map = exppb(-time*hf, [x, p]) -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: 9.9001665555952290e-01 1 1 0 - 1: 9.9666999841313930e-01 1 0 1 -------------------------------------------------- - 2: -1.9933399968262787e-02 1 1 0 - 2: 9.9001665555952378e-01 1 0 1 +work_low[1] = outx_low # Length >= length(m) = length(m2) +work_low[2] = m2x_low # Length >= length(m2) = length(m) +work_low[3] = m1x_low # Length >= length(m1) ``` -""" -function exppb(F::Vector{<:Union{TPS,ComplexTPS}}, m::Vector{<:Union{TPS,ComplexTPS}}=vars(first(F))) - descF = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(F[1].tpsa).d)) - if length(F) != descF.nv - error("Vector length != number of variables in the GTPSA") - end - ma1, mb1 = promote(F, m) - m1 = map(t->t.tpsa, ma1) - m2 = map(t->t.tpsa, mb1) - mc = zero.(ma1) - m3 = map(t->t.tpsa, mc) - GC.@preserve ma1 mb1 exppb!(Cint(length(F)), m1, m2, m3) - return mc -end - -# --- logpb --- -logpb!(na::Cint, ma::Vector{Ptr{RTPSA}}, mb::Vector{Ptr{RTPSA}}, mc::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_logpb!(na, ma, mb, mc)) -logpb!(na::Cint, ma::Vector{Ptr{CTPSA}}, mb::Vector{Ptr{CTPSA}}, mc::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_logpb!(na, ma, mb, mc)) - -""" - logpb(mf::Vector{<:Union{TPS,ComplexTPS}}, mi::Vector{<:Union{TPS,ComplexTPS}}=vars(first(F))) - -Given a final map `mf` and initial map `mi`, this function calculates the vector field `F` -such that `mf=exp(F⋅∇)mi`. If `mi` is not provided, it is assumed to be the identity. - -```julia-repl -julia> d = Descriptor(2,10); x = vars()[1]; p = vars()[2]; - -julia> time = 0.01; k = 2; m = 0.01; - -julia> h = p^2/(2m) + 1/2*k*x^2; - -julia> hf = getvectorfield(h); - -julia> map = exppb(-time*hf); -julia> logpb(map) == -time*hf -true -``` -""" -function logpb(mf::Vector{<:Union{TPS,ComplexTPS}}, mi::Vector{<:Union{TPS,ComplexTPS}}=vars(first(mf))) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(mf[1].tpsa).d)) - if length(mf) != desc.nv || length(mi) != desc.nv - error("Vector length != number of variables in the GTPSA") +If promotion is occuring, then one of the input vectors must be promoted to `ComplexTPS`. A vector of pre-allocated +`ComplexTPS`s can optionally provided as the first argument in the `work_prom` tuple, and has the requirement: + +If `eltype(m.x) != eltype(m1.x)` (then `m1` must be promoted): +`work_prom[1] = m1x_prom # Length >= length(m1), Vector{ComplexTPS}` + +else if `eltype(m.x) != eltype(m2.x)` (then `m2` must be promoted): +`work_prom[1] = m2x_prom # Length >= length(m2) = length(m), Vector{ComplexTPS}` + +Note that the `ComplexTPS`s in the vectors must be allocated and have the same `Descriptor`. +""" +function compose!(m::Vector{<:Union{TPS,ComplexTPS}}, m2::Vector{<:Union{TPS,ComplexTPS}}, m1::Vector{<:Union{TPS,ComplexTPS}}; work_low::Union{Nothing,Tuple{Vararg{Vector{<:Union{Ptr{RTPSA},Ptr{CTPSA}}}}}}=nothing, work_prom::Union{Nothing,Tuple{Vararg{Vector{<:ComplexTPS}}}}=nothing) + desc = getdesc(first(m)) + n = length(m) + n2 = length(m2) + n1 = length(m1) + + @assert n == n2 "Incorrect output length, received length $(length(m)) but need $(length(m2))" + @assert numnn(first(m2)) == n1 "Not enough input arguments" + @assert !(m === m1) "Cannot compose!(m, m2, m1) with m === m1" + @assert eltype(m) == promote_type(eltype(m2),eltype(m1)) "Cannot compose: output vector type $(eltype(m)) must be $(promote_type(eltype(m2),eltype(m1)))" + outT = eltype(m) + + if !isnothing(work_low) + outx_low = work_low[1] + m2x_low = work_low[2] + m1x_low = work_low[3] + @assert length(outx_low) >= n "Incorrect length for work_low[1] = outx_low. Received $(length(outx_low)), should be >=$n" + @assert length(m2x_low) >= n2 "Incorrect length for work_low[2] = m2x_low. Received $(length(m2x_low)), should be >=$n2" + @assert length(m1x_low) >= n1 "Incorrect length for work_low[3] = m1x_low. Received $(length(m1x_low)), should be >=$n1" + else + outx_low = Vector{lowtype(outT)}(undef, n) + m2x_low = Vector{lowtype(outT)}(undef, n) + m1x_low = Vector{lowtype(outT)}(undef, n1) end - ma1, mb1 = promote(mf, mi) - m1 = map(t->t.tpsa, ma1) - m2 = map(t->t.tpsa, mb1) - mc = zero.(ma1) - m3 = map(t->t.tpsa, mc) - GC.@preserve ma1 mb1 logpb!(Cint(length(mf)), m1, m2, m3) - return mc -end - -# --- F . grad --- -fgrad!(na::Cint, ma::Vector{Ptr{RTPSA}}, b::Ptr{RTPSA}, c::Ptr{RTPSA}) = (@inline; mad_tpsa_fgrad!(na, ma, b, c)) -fgrad!(na::Cint, ma::Vector{Ptr{CTPSA}}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = (@inline; mad_ctpsa_fgrad!(na, ma, b, c)) - -""" - fgrad(F::Vector{<:Union{TPS,ComplexTPS}}, g::Union{TPS,ComplexTPS}) -Calculates `F⋅∇g`. -""" -function fgrad(F::Vector{<:Union{TPS,ComplexTPS}}, g::Union{TPS,ComplexTPS}) - descF = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(F[1].tpsa).d)) - if length(F) != descF.nv - error("Vector length != number of variables in the GTPSA") + if !isnothing(work_prom) + if outT != eltype(m1) + m1x_prom = work_prom[1] + m2x_prom = nothing + @assert length(m1x_prom) >= n1 "Incorrect length for work_prom[1] = m1x_prom: Received $(length(m1x_prom)), should be >=$n1" + elseif outT != eltype(m2) + m1x_prom = nothing + m2x_prom = work_prom[1] + @assert length(m2x_prom) >= n "Incorrect length for work_prom[1] = m2x_prom: Received $(length(m2x_prom)), should be >=$n" + else + m1x_prom = nothing + m2x_prom = nothing + end + else + if outT != eltype(m1) + m1x_prom = Vector{ComplexTPS}(undef, n1) + for i=1:n1 # Allocate + @inbounds m1x_prom[i] = ComplexTPS(use=desc) + end + m2x_prom = nothing + elseif outT != eltype(m2) + m1x_prom = nothing + m2x_prom = Vector{ComplexTPS}(undef, n) + for i=1:n + @inbounds m2x_prom[i] = ComplexTPS(use=desc) + end + else + m1x_prom = nothing + m2x_prom = nothing + end end - type = promote_type(typeof(F[1]), typeof(g)) - ma1 = convert(Vector{type}, F) - b1 = convert(type, g) - m1 = map(t->t.tpsa, ma1) - c = zero(b1) - GC.@preserve ma1 fgrad!(Cint(length(ma)), m1, b1.tpsa, c.tpsa) - return c -end - -# --- mnrm --- -mnrm(na::Cint, ma::Vector{Ptr{RTPSA}})::Float64 = mad_tpsa_mnrm(na, ma) -mnrm(na::Cint, ma::Vector{Ptr{CTPSA}})::ComplexF64 = mad_ctpsa_mnrm(na, ma) - -#= -""" - norm(ma::Vector{<:Union{TPS,ComplexTPS}}) - -Calculates the norm of the map `ma`, defined as `sum(norm.(ma))` or the -sum of the absolute value of all coefficients in each TPS. -""" -function norm(ma::Vector{<:Union{TPS,ComplexTPS}}) - return mnrm(Cint(length(ma)), map(x->x.tpsa, ma)) -end -=# -# --- map inversion --- -minv!(na::Cint, ma::Vector{Ptr{RTPSA}}, mc::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_minv!(na, ma, mc)) -minv!(na::Cint, ma::Vector{Ptr{CTPSA}}, mc::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_minv!(na, ma, mc)) - -""" - inv(ma::Vector{<:Union{TPS,ComplexTPS}}) - -Inverts the map `ma` such that `ma ∘ inv(ma) = 1` in the variables. - -# Example - -```julia-repl - -julia> d = Descriptor(2,10); x = vars()[1]; p = vars()[2]; - -julia> time = 0.01; k = 2; m = 0.01; - -julia> h = p^2/(2m) + 1/2*k*x^2; - -julia> hf = getvectorfield(h); -julia> map = exppb(-time*hf, [x, p]); + # Do the composition, promoting if necessary + if outT != eltype(m1) + # Promote to ComplexTPS: + for i=1:n1 + @inbounds complex!(m1x_prom[i], m1[i]) + end + map!(t->t.tpsa, m1x_low, m1x_prom) + else + map!(t->t.tpsa, m1x_low, m1) + end -julia> map ∘ inv(map) -2-element Vector{TPS}: - Out Coefficient Order Exponent -------------------------------------------------- - 1: 1.0000000000000000e+00 1 1 0 -------------------------------------------------- - 2: 1.0000000000000002e+00 1 0 1 -``` -""" -function inv(ma::Vector{<:Union{TPS,ComplexTPS}}) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(ma[1].tpsa).d)) - if length(ma) != desc.nv - error("Map length != number of variables in the GTPSA") + if outT != eltype(m2) + # Promote to ComplexTPS: + for i=1:n + @inbounds complex!(m2x_prom[i], m2[i]) + end + map!(t->t.tpsa, m2x_low, m2x_prom) + else + map!(t->t.tpsa, m2x_low, m2) end - mc = zero.(ma) - ma1 = map(x->x.tpsa, ma) - mc1 = map(x->x.tpsa, mc) - minv!(Cint(length(ma)), ma1, mc1) - return mc -end -# --- partial inversion --- -pminv!(na::Cint, ma::Vector{Ptr{RTPSA}}, mc::Vector{Ptr{RTPSA}}, select::Vector{Cint}) = (@inline; mad_tpsa_pminv!(na, ma, mc, select)) -pminv!(na::Cint, ma::Vector{Ptr{CTPSA}}, mc::Vector{Ptr{CTPSA}}, select::Vector{Cint}) = (@inline; mad_ctpsa_pminv!(na, ma, mc, select)) + # go low + map!(t->t.tpsa, outx_low, m) -""" - ptinv(ma::Vector{<:Union{TPS,ComplexTPS}}, vars::Vector{<:Integer}) + GC.@preserve m1x_prom m2x_prom compose!(Cint(n), m2x_low, Cint(n1), m1x_low, outx_low) -Partially-inverts the map `ma`, inverting only the variables specified by index -in `vars`. -""" -function ptinv(ma::Vector{<:Union{TPS,ComplexTPS}}, vars::Vector{<:Integer}) - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(ma[1].tpsa).d)) - if length(ma) != desc.nv - error("Map length != number of variables in the GTPSA") - end - mc = zero.(ma) - ma1 = map(x->x.tpsa, ma) - mc1 = map(x->x.tpsa, mc) - na = Cint(length(ma)) - select = zeros(Cint, na) - select[vars] .= Cint(1) - pminv!(na, ma1, mc1, select) - return mc + return end -# --- composition --- -compose!(na::Cint, ma::Vector{Ptr{RTPSA}}, nb::Cint, mb::Vector{Ptr{RTPSA}}, mc::Vector{Ptr{RTPSA}}) = (@inline; mad_tpsa_compose!(na, ma, nb, mb, mc)) -compose!(na::Cint, ma::Vector{Ptr{CTPSA}}, nb::Cint, mb::Vector{Ptr{CTPSA}}, mc::Vector{Ptr{CTPSA}}) = (@inline; mad_ctpsa_compose!(na, ma, nb, mb, mc)) - function ∘(ma::Vector{<:Union{TPS,ComplexTPS}}, mb::Vector{<:Union{TPS,ComplexTPS}}) na = Cint(length(ma)) nb = Cint(length(mb)) # Ensure mb is length = input - desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(ma[1].tpsa).d)) - if desc.nv + desc.np != nb + desc = getdesc(first(ma)) + if numnn(desc) != nb error("Not enough input arguments") end - ma1, mb1 = promote(ma, mb) - m1 = map(t->t.tpsa, ma1) - m2 = map(t->t.tpsa, mb1) - mc = Vector{typeof(ma1[1])}(undef, na) - for i in eachindex(mc) - mc[i] = zero(ma1[1]) + outT = promote_type(eltype(ma),eltype(mb)) + mc = Vector{outT}(undef, na) + for i=1:na + @inbounds mc[i] = outT(use=desc) end - m3 = map(t->t.tpsa, mc) - GC.@preserve ma1 mb1 compose!(na, m1, nb, m2, m3) + compose!(mc, ma, mb) return mc end compose = ∘ # --- translate --- +translate!(na::Cint, ma::Vector{Ptr{RTPSA}}, nb::Cint, tb::Vector{Float64}, mc::Vector{Ptr{RTPSA}}) = mad_tpsa_translate!(na, ma, nb, tb, mc) +translate!(na::Cint, ma::Vector{Ptr{CTPSA}}, nb::Cint, tb::Vector{ComplexF64}, mc::Vector{Ptr{CTPSA}}) = mad_ctpsa_translate!(na, ma, nb, tb, mc) + + """ - translate(m::Vector{TPS}, x::Vector{<:Real})::Vector{TPS} + translate!(mc::Vector{<:T}, ma::Vector{<:T}, tb::Vector{<:Number}) where {T<:Union{TPS,ComplexTPS}} -Translates the expansion point of the Vector of TPSs `m` by `x`. +Fills `ma` with the vector function equal to `ma` with its expansion point translated by `tb`. + +Two temporary vectors of either `Ptr{RTPSA}` or `Ptr{CTPSA}` must be created, or they can optionally +be passed as a tuple to the kwarg `work_low` where + +`ma_low` = low corresponding to `ma` = `work_low[1]` +`mb_low` = low corresponding to `mb` = `work_low[2]` """ -function translate(m::Vector{TPS}, x::Vector{<:Real})::Vector{TPS} - na = Cint(length(m)) - nb = Cint(length(x)) - tb = convert(Vector{Float64}, x) - ma1 = map(x->x.tpsa, m) - mc = zero.(m) - mc1 = map(x->x.tpsa, mc) - mad_tpsa_translate!(na, ma1, nb, tb, mc1) - return mc +function translate!(mc::Vector{<:T}, ma::Vector{<:T}, tb::Vector{<:Number}; work_low::Union{Nothing,Tuple{Vararg{Vector{<:Union{Ptr{RTPSA},Ptr{CTPSA}}}}}}=nothing) where {T<:Union{TPS,ComplexTPS}} + desc = getdesc(first(ma)) + nb = Cint(length(tb)) + na = Cint(length(ma)) + numnn(desc) == nb || error("Not enough input arguments") + length(mc) == na || error("Output vector length != input vector length") + eltype(tb) == numtype(T) || error("Translation vector must have eltype $(numtype(T))") + if !isnothing(work_low) + ma_low = work_low[1] + mc_low = work_low[2] + else + ma_low = map(t->t.tpsa, ma) + mc_low = map(t->t.tpsa, mc) + end + translate!(na, ma_low, nb, tb, mc_low) end """ - translate(m::Vector{ComplexTPS}, x::Vector{<:Number})::Vector{ComplexTPS} - -Translates the expansion point of the Vector of TPSs `m` by `x`. +Returns a vector function equal to `ma` with its expansion point translated by `tb` """ -function translate(m::Vector{ComplexTPS}, x::Vector{<:Number})::Vector{ComplexTPS} - na = Cint(length(m)) - nb = Cint(length(x)) - tb = convert(Vector{ComplexF64}, x) - ma1 = map(x->x.tpsa, m) - mc = zero.(m) - mc1 = map(x->x.tpsa, mc) - mad_ctpsa_translate!(na, ma1, nb, tb, mc1) +function translate(ma::Vector{<:T}, tb::Vector{<:Number}) where {T<:Union{TPS,ComplexTPS}} + desc = getdesc(first(ma)) + nc = length(ma) + mc = Vector{T}(undef, nc) + for i=1:nc + mc[i] = T(use=desc) + end + translate!(mc, ma, convert(Vector{numtype(T)}, tb)) return mc end \ No newline at end of file diff --git a/src/operators.jl b/src/operators.jl index 3ad84c58..5a899a5c 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -1,4 +1,17 @@ -# -- zero -- +# --- copy --- +function copy!(t::TPS, t1::TPS) + mad_tpsa_copy!(t1.tpsa, t.tpsa) +end + +function copy!(ct::ComplexTPS, t1::TPS) + mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ct.tpsa) +end + +function copy!(ct::ComplexTPS, ct1::ComplexTPS) + mad_ctpsa_copy!(ct1.tpsa, ct.tpsa) +end + +# --- zero --- function zero(t::TPS)::TPS return TPS(mad_tpsa_new(t.tpsa, MAD_TPSA_SAME)) end @@ -10,16 +23,54 @@ end # --- one --- function one(t1::TPS)::TPS t = TPS(mad_tpsa_new(t1.tpsa, MAD_TPSA_SAME)) - mad_tpsa_set0!(t.tpsa, 0.0, 1.0) + mad_tpsa_seti!(t.tpsa, Cint(0), 0.0, 1.0) return t end function one(ct1::ComplexTPS)::ComplexTPS ct = ComplexTPS(mad_ctpsa_new(ct1.tpsa, MAD_TPSA_SAME)) - mad_ctpsa_set0!(ct.tpsa, ComplexF64(0.0), ComplexF64(1.0)) + mad_ctpsa_seti!(ct.tpsa, Cint(0), ComplexF64(0.0), ComplexF64(1.0)) return ct end +# --- zeros and ones (taken from Base.array.jl) --- +# We overload this because we want each element of the array to be a separate allocated TPS +for (fname, felt) in ((:zeros, :zero), (:ones, :one)) + @eval begin + $fname(::Type{T}, dims::Base.DimOrInd...) where {T<:Union{TPS,ComplexTPS}} = $fname(T, dims) + $fname(::Type{T}, dims::NTuple{N, Union{Integer, Base.OneTo}}) where {T<:Union{TPS,ComplexTPS},N} = $fname(T, map(to_dim, dims)) + function $fname(::Type{T}, dims::NTuple{N, Integer}) where {T<:Union{TPS,ComplexTPS},N} + a = Array{T,N}(undef, dims) + for idx in eachindex(a) + a[idx] = $felt(T) + end + return a + end + function $fname(::Type{T}, dims::Tuple{}) where {T<:Union{TPS,ComplexTPS}} + a = Array{T}(undef) + for idx in eachindex(a) + a[idx] = $felt(T) + end + return a + end + end +end + +# --- rand --- +""" + rand(::Type{T}; use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current) where {T<:Union{TPS,ComplexTPS}} + +Generate a `TPS`/`ComplexTPS` with all random coefficients. +""" +function rand(::Type{T}; use::Union{Descriptor,TPS,ComplexTPS}=GTPSA.desc_current) where {T<:Union{TPS,ComplexTPS}} + t = T(use=use) + len = length(t) + for i=0:len-1 + t[i] = rand(numtype(T)) + end + return t +end + # --- Unary --- # TPS: function +(t1::TPS)::TPS @@ -72,15 +123,15 @@ end # isequal, just as Dual Numbers. function <(t1::TPS, t2::TPS)::Bool - return mad_tpsa_get0(t1.tpsa) < mad_tpsa_get0(t2.tpsa) + return mad_tpsa_geti(t1.tpsa, Cint(0)) < mad_tpsa_geti(t2.tpsa, Cint(0)) end function <(t1::TPS, a::Real)::Bool - return mad_tpsa_get0(t1.tpsa) < a + return mad_tpsa_geti(t1.tpsa, Cint(0)) < a end function <(a::Real, t1::TPS)::Bool - return a < mad_tpsa_get0(t1.tpsa) + return a < mad_tpsa_geti(t1.tpsa, Cint(0)) end function >(t1::TPS, t2::TPS)::Bool @@ -96,15 +147,15 @@ function >(a::Real, t1::TPS)::Bool end function <=(t1::TPS, t2::TPS)::Bool - return mad_tpsa_get0(t1.tpsa) <= mad_tpsa_get0(t2.tpsa) + return mad_tpsa_geti(t1.tpsa, Cint(0)) <= mad_tpsa_geti(t2.tpsa, Cint(0)) end function <=(t1::TPS, a::Real)::Bool - return mad_tpsa_get0(t1.tpsa) <= a + return mad_tpsa_geti(t1.tpsa, Cint(0)) <= a end function <=(a::Real, t1::TPS)::Bool - return a <= mad_tpsa_get0(t1.tpsa) + return a <= mad_tpsa_geti(t1.tpsa, Cint(0)) end function >=(t1::TPS, t2::TPS)::Bool @@ -122,44 +173,44 @@ end # Note Complex numbers/TPSs have no defined >, < function ==(t1::TPS, t2::TPS)::Bool - return mad_tpsa_get0(t1.tpsa) == mad_tpsa_get0(t2.tpsa) + return mad_tpsa_geti(t1.tpsa, Cint(0)) == mad_tpsa_geti(t2.tpsa, Cint(0)) end function ==(t1::TPS, a::Number)::Bool - return mad_tpsa_get0(t1.tpsa) == a + return mad_tpsa_geti(t1.tpsa, Cint(0)) == a end function ==(a::Number,t1::TPS)::Bool - return mad_tpsa_get0(t1.tpsa) == a + return mad_tpsa_geti(t1.tpsa, Cint(0)) == a end # --- function ==(t1::TPS, a::Complex)::Bool - return mad_tpsa_get0(t1.tpsa) == a + return mad_tpsa_geti(t1.tpsa, Cint(0)) == a end function ==(a::Complex,t1::TPS)::Bool - return mad_tpsa_get0(t1.tpsa) == a + return mad_tpsa_geti(t1.tpsa, Cint(0)) == a end # --- function ==(ct1::ComplexTPS, ct2::ComplexTPS)::Bool - return mad_ctpsa_get0(ct1.tpsa) == mad_ctpsa_get0(ct2.tpsa) + return mad_ctpsa_geti(ct1.tpsa, Cint(0)) == mad_ctpsa_geti(ct2.tpsa, Cint(0)) end function ==(ct1::ComplexTPS, a::Number)::Bool - return mad_ctpsa_get0(ct1.tpsa) == a + return mad_ctpsa_geti(ct1.tpsa, Cint(0)) == a end function ==(a::Number, ct1::ComplexTPS)::Bool - return mad_ctpsa_get0(ct1.tpsa) == a + return mad_ctpsa_geti(ct1.tpsa, Cint(0)) == a end function ==(ct1::ComplexTPS, t1::TPS)::Bool - return mad_ctpsa_get0(ct1.tpsa) == mad_tpsa_get0(t1.tpsa) + return mad_ctpsa_geti(ct1.tpsa, Cint(0)) == mad_tpsa_geti(t1.tpsa, Cint(0)) end function ==(t1::TPS, ct1::ComplexTPS)::Bool @@ -217,255 +268,126 @@ function isequal(t1::TPS, ct1::ComplexTPS)::Bool return isequal(ct1, t1) end - # --- add --- -# TPS: -function +(t1::TPS, t2::TPS)::TPS - t = zero(t1) - mad_tpsa_add!(t1.tpsa, t2.tpsa, t.tpsa) - return t -end +# TPS, TPS: +add!(a::Ptr{RTPSA}, b::Ptr{RTPSA}, c::Ptr{RTPSA}) = mad_tpsa_add!(a, b, c) +add!(a::Ptr{CTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_add!(a, b, c) +add!(a::Ptr{RTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_addt!(b, a, c) +add!(a::Ptr{CTPSA}, b::Ptr{RTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_addt!(a, b, c) -function +(t1::TPS, a::Real)::TPS - t = TPS(t1) - mad_tpsa_set0!(t.tpsa, 1., convert(Float64,a)) - return t -end +add!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, t2::Union{TPS,ComplexTPS}) = add!(t1.tpsa, t2.tpsa, t.tpsa) -function +(a::Real, t1::TPS)::TPS - return t1 + a -end +# TPS, scalar: -# ComplexTPS: -function +(ct1::ComplexTPS, ct2::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_add!(ct1.tpsa, ct2.tpsa, ct.tpsa) - return ct -end - -function +(ct1::ComplexTPS, a::Number)::ComplexTPS - ct = ComplexTPS(ct1) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) - return ct +function add!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, a::Number) + copy!(t, t1) + seti!(t.tpsa, Cint(0), convert(numtype(t), 1), convert(numtype(t), a)) end -function +(a::Number, ct1::ComplexTPS)::ComplexTPS - return ct1 + a -end - -# TPS to ComplexTPS promotion, w/o creating temp ComplexTPS: -function +(ct1::ComplexTPS, t1::TPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_addt!(ct1.tpsa, t1.tpsa, ct.tpsa) - return ct -end +add!(t::Union{TPS,ComplexTPS}, a::Number, t1::Union{TPS,ComplexTPS}) = add!(t, t1, a) -function +(t1::TPS, ct1::ComplexTPS)::ComplexTPS - return ct1 + t1 +for t = ((TPS,TPS),(TPS,Real),(Real,TPS),(TPS,Complex),(Complex,TPS),(ComplexTPS,TPS),(TPS,ComplexTPS),(ComplexTPS,ComplexTPS),(ComplexTPS, Number), (Number, ComplexTPS)) +@eval begin +function +(t1::$t[1], t2::$t[2]) + use = $(t[1] == TPS || t[1] == ComplexTPS ? :t1 : :t2) + t = (promote_type(typeof(t1),typeof(t2)))(use=use) + add!(t, t1, t2) + return t end - -function +(t1::TPS, a::Complex)::ComplexTPS - ct = ComplexTPS(t1) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, a)) - return ct end - -function +(a::Complex, t1::TPS)::ComplexTPS - return t1 + a end # --- sub --- -# TPS: -function -(t1::TPS, t2::TPS)::TPS - t = zero(t1) - mad_tpsa_sub!(t1.tpsa, t2.tpsa, t.tpsa) - return t -end +# TPS, TPS: +sub!(a::Ptr{RTPSA}, b::Ptr{RTPSA}, c::Ptr{RTPSA}) = mad_tpsa_sub!(a, b, c) +sub!(a::Ptr{CTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_sub!(a, b, c) +sub!(a::Ptr{CTPSA}, b::Ptr{RTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_subt!(a, b, c) +sub!(a::Ptr{RTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_tsub!(a, b, c) +sub!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, t2::Union{TPS,ComplexTPS}) = sub!(t1.tpsa, t2.tpsa, t.tpsa) -function -(t1::TPS, a::Real)::TPS - t = TPS(t1) - mad_tpsa_set0!(t.tpsa, 1., convert(Float64, -a)) - return t +# TPS, scalar: +scl!(a::Ptr{RTPSA}, v::Float64, c::Ptr{RTPSA}) = mad_tpsa_scl!(a, v, c) +scl!(a::Ptr{CTPSA}, v::ComplexF64, c::Ptr{CTPSA}) = mad_ctpsa_scl!(a, v, c) +function scl!(a::Ptr{RTPSA}, v::ComplexF64, c::Ptr{CTPSA}) + mad_ctpsa_cplx!(a, Base.unsafe_convert(Ptr{RTPSA},C_NULL), c) + scl!(c, v, c) end -function -(a::Real, t1::TPS)::TPS - t = zero(t1) - mad_tpsa_scl!(t1.tpsa, -1., t.tpsa) - mad_tpsa_set0!(t.tpsa, 1., convert(Float64, a)) - return t -end - -# ComplexTPS: -function -(ct1::ComplexTPS, ct2::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_sub!(ct1.tpsa, ct2.tpsa, ct.tpsa) - return ct -end +sub!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, a::Number) = add!(t, t1, -a) -function -(ct1::ComplexTPS, a::Number)::ComplexTPS - ct = ComplexTPS(ct1) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, -a)) - return ct +function sub!(t::Union{TPS,ComplexTPS}, a::Number, t1::Union{TPS,ComplexTPS}) + scl!(t1.tpsa, convert(numtype(t), -1.), t.tpsa) + seti!(t.tpsa, Cint(0), convert(numtype(t), 1.), convert(numtype(t), a)) end -function -(a::Number, ct1::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_scl!(ct1.tpsa, convert(ComplexF64, -1), ct.tpsa) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64,a)) - return ct +for t = ((TPS,TPS),(TPS,Real),(Real,TPS),(TPS,Complex),(Complex,TPS),(ComplexTPS,TPS),(TPS,ComplexTPS),(ComplexTPS,ComplexTPS),(ComplexTPS, Number), (Number, ComplexTPS)) +@eval begin +function -(t1::$t[1], t2::$t[2]) + use = $(t[1] == TPS || t[1] == ComplexTPS ? :t1 : :t2) + t = (promote_type(typeof(t1),typeof(t2)))(use=use) + sub!(t, t1, t2) + return t end - -# TPS to ComplexTPS promotion, w/o creating temp ComplexTPS: -function -(ct1::ComplexTPS, t1::TPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_subt!(ct1.tpsa, t1.tpsa, ct.tpsa) - return ct end - -function -(t1::TPS, ct1::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_tsub!(t1.tpsa, ct1.tpsa, ct.tpsa) - return ct end -function -(t1::TPS, a::Complex)::ComplexTPS - ct = ComplexTPS(t1) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64, -a)) - return ct -end - -function -(a::Complex, t1::TPS)::ComplexTPS - ct = ComplexTPS(t1) - mad_ctpsa_scl!(ct.tpsa, convert(ComplexF64, -1), ct.tpsa) - mad_ctpsa_set0!(ct.tpsa, convert(ComplexF64, 1), convert(ComplexF64,a)) - return ct -end - - # --- mul --- -# TPS: -function *(t1::TPS, t2::TPS)::TPS - t = zero(t1) - mad_tpsa_mul!(t1.tpsa, t2.tpsa, t.tpsa) +# TPS, TPS: +mul!(a::Ptr{RTPSA}, b::Ptr{RTPSA}, c::Ptr{RTPSA}) = mad_tpsa_mul!(a, b, c) +mul!(a::Ptr{CTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_mul!(a, b, c) +mul!(a::Ptr{RTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_mult!(b, a, c) +mul!(a::Ptr{CTPSA}, b::Ptr{RTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_mult!(a, b, c) + +mul!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, t2::Union{TPS,ComplexTPS}) = mul!(t1.tpsa, t2.tpsa, t.tpsa) + +# TPS, scalar: +mul!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, a::Number) = scl!(t1.tpsa, convert(numtype(t), a), t.tpsa) +mul!(t::Union{TPS,ComplexTPS}, a::Number, t1::Union{TPS,ComplexTPS}) = mul!(t, t1, a) + +for t = ((TPS,TPS),(TPS,Real),(Real,TPS),(TPS,Complex),(Complex,TPS),(ComplexTPS,TPS),(TPS,ComplexTPS),(ComplexTPS,ComplexTPS),(ComplexTPS, Number), (Number, ComplexTPS)) +@eval begin +function *(t1::$t[1], t2::$t[2]) + use = $(t[1] == TPS || t[1] == ComplexTPS ? :t1 : :t2) + t = (promote_type(typeof(t1),typeof(t2)))(use=use) + mul!(t, t1, t2) return t end - -function *(t1::TPS, a::Real)::TPS - t = zero(t1) - mad_tpsa_scl!(t1.tpsa, convert(Float64, a), t.tpsa) - return t -end - -function *(a::Real, t1::TPS)::TPS - return t1 * a -end - -# ComplexTPS: -function *(ct1::ComplexTPS, ct2::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_mul!(ct1.tpsa, ct2.tpsa, ct.tpsa) - return ct -end - -function *(ct1::ComplexTPS, a::Number)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_scl!(ct1.tpsa, convert(ComplexF64,a), ct.tpsa) - return ct -end - -function *(a::Number, ct1::ComplexTPS)::ComplexTPS - return ct1 * a end - -# TPS to ComplexTPS promotion, w/o creating temp ComplexTPS: -function *(ct1::ComplexTPS, t1::TPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_mult!(ct1.tpsa, t1.tpsa, ct.tpsa) - return ct -end - -function *(t1::TPS, ct1::ComplexTPS)::ComplexTPS - return ct1 * t1 -end - -function *(t1::TPS, a::Complex)::ComplexTPS - ct = ComplexTPS(t1) - mad_ctpsa_scl!(ct.tpsa, convert(ComplexF64,a), ct.tpsa) - return ct -end - -function *(a::Complex, t1::TPS)::ComplexTPS - return t1 * a end # --- div --- -# TPS: -function /(t1::TPS, t2::TPS)::TPS - t = zero(t1) - mad_tpsa_div!(t1.tpsa, t2.tpsa, t.tpsa) +div!(a::Ptr{RTPSA}, b::Ptr{RTPSA}, c::Ptr{RTPSA}) = mad_tpsa_div!(a, b, c) +div!(a::Ptr{CTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_div!(a, b, c) +div!(a::Ptr{CTPSA}, b::Ptr{RTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_divt!(a, b, c) +div!(a::Ptr{RTPSA}, b::Ptr{CTPSA}, c::Ptr{CTPSA}) = mad_ctpsa_tdiv!(a, b, c) + +div!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, t2::Union{TPS,ComplexTPS}) = div!(t1.tpsa, t2.tpsa, t.tpsa) + +# TPS, scalar: +inv!(a::Ptr{RTPSA}, v::Float64, c::Ptr{RTPSA}) = mad_tpsa_inv!(a, v, c) +inv!(a::Ptr{CTPSA}, v::ComplexF64, c::Ptr{CTPSA}) = mad_ctpsa_inv!(a, v, c) +function inv!(a::Ptr{RTPSA}, v::ComplexF64, c::Ptr{CTPSA}) + mad_ctpsa_cplx!(a, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), c) + inv!(c, v, c) +end + +div!(t::Union{TPS,ComplexTPS}, t1::Union{TPS,ComplexTPS}, a::Number) = mul!(t, t1, 1/a) +div!(t::Union{TPS,ComplexTPS}, a::Number, t1::Union{TPS,ComplexTPS}) = inv!(t1.tpsa, convert(numtype(t), a), t.tpsa) + +for t = ((TPS,TPS),(TPS,Real),(Real,TPS),(TPS,Complex),(Complex,TPS),(ComplexTPS,TPS),(TPS,ComplexTPS),(ComplexTPS,ComplexTPS),(ComplexTPS, Number), (Number, ComplexTPS)) +@eval begin +function /(t1::$t[1], t2::$t[2]) + use = $(t[1] == TPS || t[1] == ComplexTPS ? :t1 : :t2) + t = (promote_type(typeof(t1),typeof(t2)))(use=use) + div!(t, t1, t2) return t end - -function /(t1::TPS, a::Real)::TPS - t = zero(t1) - mad_tpsa_scl!(t1.tpsa, convert(Float64, 1/a), t.tpsa) - return t -end - -function /(a::Real, t1::TPS)::TPS - t = zero(t1) - mad_tpsa_inv!(t1.tpsa, convert(Float64,a), t.tpsa) - return t end - -# ComplexTPS: -function /(ct1::ComplexTPS, ct2::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_div!(ct1.tpsa, ct2.tpsa, ct.tpsa) - return ct -end - -function /(ct1::ComplexTPS, a::Number)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_scl!(ct1.tpsa, convert(ComplexF64, 1/a), ct.tpsa) - return ct -end - -function /(a::Number, ct1::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_inv!(ct1.tpsa, convert(ComplexF64, a), ct.tpsa) - return ct end -# TPS to ComplexTPS promotion, w/o creating temp ComplexTPS: -function /(ct1::ComplexTPS, t1::TPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_divt!(ct1.tpsa, t1.tpsa, ct.tpsa) - return ct -end - -function /(t1::TPS, ct1::ComplexTPS)::ComplexTPS - ct = zero(ct1) - mad_ctpsa_tdiv!(t1.tpsa, ct1.tpsa, ct.tpsa) - return ct -end - -function /(t1::TPS, a::Complex)::ComplexTPS - ct = ComplexTPS(t1) - mad_ctpsa_scl!(ct.tpsa, convert(ComplexF64, 1/a), ct.tpsa) - return ct -end - -function /(a::Complex, t1::TPS)::ComplexTPS - ct = ComplexTPS(t1) - mad_ctpsa_inv!(ct.tpsa, convert(ComplexF64, a), ct.tpsa) - return ct -end - - # --- pow --- # TPS: function ^(t1::TPS, t2::TPS)::TPS diff --git a/src/show.jl b/src/show.jl index ea0d2b84..0862d023 100644 --- a/src/show.jl +++ b/src/show.jl @@ -286,7 +286,7 @@ function show_vec(io::IO, m::Vector{<:Union{TPS,ComplexTPS}}) desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(first(m).tpsa).d)) diffdescs = false for i in eachindex(m) - if desc != unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(m[i].tpsa).d)) + if !diffdescs && desc != unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(m[i].tpsa).d)) println(io, "WARNING: Atleast one $(eltype(m)) has a different Descriptor!") diffdescs = true lines_used[] += 1 @@ -330,7 +330,9 @@ function show_map!(io::IO, m::Vector{<:Union{TPS,ComplexTPS}}, lines_used::Ref=R for i in eachindex(m) curdesc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(m[i].tpsa).d)) if only_vars && (desc.nv != curdesc.nv) - error("Cannot use only_vars = true for vector with TPSs having different number of variables") + println(io, "Cannot print $(typeof(m)): unable to resolve GTPSA Descriptor.") + lines_used[]+=1 + return end max_nn = max(max_nn, curdesc.nv+curdesc.np) end diff --git a/src/tps.jl b/src/tps.jl new file mode 100644 index 00000000..a506f254 --- /dev/null +++ b/src/tps.jl @@ -0,0 +1,248 @@ +# Wrapper struct for Ptr{RTPSA} +mutable struct TPS <: Real + tpsa::Ptr{RTPSA} + function TPS(t1::Ptr{RTPSA})::TPS + t = new(t1) + f(x) = mad_tpsa_del!(x.tpsa) + finalizer(f,t) + return t + end +end + +# Wrapper struct for Ptr{CTPSA} +mutable struct ComplexTPS <: Number + tpsa::Ptr{CTPSA} + function ComplexTPS(ct1::Ptr{CTPSA})::ComplexTPS + ct = new(ct1) + f(x) = mad_ctpsa_del!(x.tpsa) + finalizer(f,ct) + return ct + end +end + +""" + TPS(ta::Union{Real,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::TPS + +Constructor to create a new `TPS` equal to the real value `ta`. If `ta` is a `TPS`, this +is equivalent to a copy constructor, with the result by default having the same `Descriptor` as `ta`. +If `ta` is not a `TPS`, then the `Descriptor` used will by default be `GTPSA.desc_current`. The `Descriptor` +for the constructed `TPS` can be set using `use`. If a `TPS` or `ComplexTPS` is passed to `use`, +the `Descriptor` for that TPS will be used. + +The constructor can also be used to create a copy of a `TPS` under one `Descriptor` to instead +have a different `Descriptor`. In this case, invalid monomials under the new `Descriptor` are removed. + +### Input +- `ta` -- Any `Real` +- `use` -- (Optional) specify which `Descriptor` to use, default is `nothing` which uses the `Descriptor` for `ta` if `ta isa TPS`, else uses `GTPSA.desc_current` + +### Output +- `ret` -- New `TPS` equal to `ta` with removal of invalid monomials if `ta` is a `TPS` and a new `Descriptor` is specified +""" +function TPS(ta::Union{Real,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::TPS + return low_TPS(ta, use) +end + +# --- Blank TPS --- +function low_TPS(ta::Nothing, use::Descriptor) + return TPS(mad_tpsa_newd(use.desc, MAD_TPSA_DEFAULT)) +end + +function low_TPS(ta::Nothing, use::Union{TPS,ComplexTPS}) + return TPS(mad_tpsa_new(Base.unsafe_convert(Ptr{RTPSA}, use.tpsa), MAD_TPSA_SAME)) +end + +function low_TPS(ta::Nothing, use::Nothing) + return TPS(mad_tpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) +end + +# --- Copy ctor --- +function low_TPS(t1::TPS, use::Nothing) + t = TPS(mad_tpsa_new(t1.tpsa, MAD_TPSA_SAME)) + mad_tpsa_copy!(t1.tpsa, t.tpsa) + return t +end + +# --- Change descriptor --- +function low_TPS(t1::TPS, use::Descriptor) + return change(t1, use) +end + +function low_TPS(t1::TPS, use::Union{TPS,ComplexTPS}) + return change(t1, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa).d))) +end + +# --- promote real to TPS --- +function low_TPS(a::Real, use::Nothing) + t = TPS(mad_tpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) + mad_tpsa_seti!(t.tpsa, Cint(0), convert(Float64, 0), convert(Float64,a)) + return t +end + +function low_TPS(a::Real, use::Union{TPS,ComplexTPS}) + t = TPS(mad_tpsa_new(Base.unsafe_convert(Ptr{RTPSA}, use.tpsa), MAD_TPSA_SAME)) + mad_tpsa_seti!(t.tpsa, Cint(0), 0.0, convert(Float64,a)) + return t +end + +function low_TPS(a::Real, use::Descriptor) + t = TPS(mad_tpsa_newd(use.desc, MAD_TPSA_DEFAULT)) + mad_tpsa_seti!(t.tpsa, Cint(0), 0.0, convert(Float64,a)) + return t +end + +# ----------------------- +""" + ComplexTPS(cta::Union{Number,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::ComplexTPS + +Constructor to create a new `ComplexTPS` equal to the number `cta`. If `cta` is a `ComplexTPS` (or `TPS`), this +is equivalent to a copy constructor, with the result by default having the same `Descriptor` as `cta`. If `cta` +is not a `TPS` or`ComplexTPS`, then the `Descriptor` used will by default be `GTPSA.desc_current`. The `Descriptor` +for the constructed `ComplexTPS` can be set using `use`. If a `TPS` or `ComplexTPS` is passed to `use`, +the `Descriptor` for that TPS will be used. + +The constructor can also be used to create a copy of a `ComplexTPS` under one `Descriptor` to instead +have a different `Descriptor`. In this case, invalid monomials under the new `Descriptor` are removed. + +### Input +- `cta` -- Any `Number` +- `use` -- (Optional) specify which `Descriptor` to use, default is `nothing` which uses the `Descriptor` for `cta` if `cta <: Union{TPS,ComplexTPS}`, else uses `GTPSA.desc_current` + +### Output +- `ret` -- New `ComplexTPS` equal to `cta` with removal of invalid monomials if `cta` is a `TPS`/`ComplexTPS` and a new `Descriptor` is specified +""" +function ComplexTPS(cta::Union{Number,Nothing}=nothing; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::ComplexTPS + return low_ComplexTPS(cta, use) +end + +# For some reason I need to explicitly define this: +ComplexTPS(t::ComplexTPS; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing) = low_ComplexTPS(t,use) + +# --- Blank ComplexTPS --- +function low_ComplexTPS(cta::Nothing, use::Descriptor) + return ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) +end + +function low_ComplexTPS(cta::Nothing, use::Union{TPS,ComplexTPS}) + return ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) +end + +function low_ComplexTPS(cta::Nothing, use::Nothing) + return ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) +end + +# --- Copy ctor --- +function low_ComplexTPS(ct1::ComplexTPS, use::Nothing) + ct = ComplexTPS(mad_ctpsa_new(ct1.tpsa, MAD_TPSA_SAME)) + mad_ctpsa_copy!(ct1.tpsa, ct.tpsa) + return ct +end + +function low_ComplexTPS(t1::TPS, use::Nothing) + ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) + mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ct.tpsa) + return ct +end + +# --- Change descriptor --- +function low_ComplexTPS(t1::Union{TPS,ComplexTPS}, use::Descriptor) + return change(t1, use) +end + +function low_ComplexTPS(t1::Union{TPS,ComplexTPS}, use::Union{TPS,ComplexTPS}) + return change(t1, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa).d))) +end + +# --- promote number to ComplexTPS --- +function low_ComplexTPS(a::Union{Real,Complex}, use::Nothing) + ct = ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 0), convert(ComplexF64,a)) + return ct +end + +function low_ComplexTPS(a::Union{Real,Complex}, use::Union{TPS,ComplexTPS}) + ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 0), convert(ComplexF64,a)) + return ct +end + +function low_ComplexTPS(a::Union{Real,Complex}, use::Descriptor) + ct = ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 0), convert(ComplexF64,a)) + return ct +end + +# ----------------------- + +# Special real argument ctors +function ComplexTPS(ta::Real, tb::Real; use::Union{Descriptor,TPS,ComplexTPS,Nothing}=nothing)::ComplexTPS + low_ComplexTPS(ta, tb, use) +end + +function low_ComplexTPS(t1::TPS, t2::TPS, use::Nothing) + ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) + mad_ctpsa_cplx!(t1.tpsa, t2.tpsa, ct.tpsa) + return ct +end + +function low_ComplexTPS(t1::TPS, a::Real, use::Nothing) + ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) + mad_ctpsa_cplx!(t1.tpsa, Base.unsafe_convert(Ptr{RTPSA}, C_NULL), ct.tpsa) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64, complex(0,a))) + return ct +end + +function low_ComplexTPS(a::Real, t1::TPS, use::Nothing) + ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, t1.tpsa), MAD_TPSA_SAME)) + mad_ctpsa_cplx!(Base.unsafe_convert(Ptr{RTPSA}, C_NULL), t1.tpsa, ct.tpsa) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64, a)) + return ct +end + +function low_ComplexTPS(a::Real, b::Real, use::Nothing) + ct = ComplexTPS(mad_ctpsa_newd(GTPSA.desc_current.desc, MAD_TPSA_DEFAULT)) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) + return ct +end + +function low_ComplexTPS(a::Real, b::Real, use::Descriptor) + ct = ComplexTPS(mad_ctpsa_newd(use.desc, MAD_TPSA_DEFAULT)) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) + return ct +end + +function low_ComplexTPS(a::Real, b::Real, use::Union{TPS,ComplexTPS}) + ct = ComplexTPS(mad_ctpsa_new(Base.unsafe_convert(Ptr{CTPSA}, use.tpsa), MAD_TPSA_SAME)) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 0), convert(ComplexF64, complex(a,b))) + return ct +end + +function low_ComplexTPS(ta::TPS, tb::TPS, use::Descriptor) + ct = change(ta, use, type=ComplexTPS) + change!(ct, tb, 1, im) + return ct +end + +function low_ComplexTPS(ta::TPS, b::Real, use::Descriptor) + ct = change(ta, use, type=ComplexTPS) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64, complex(0,b))) + return ct +end + +function low_ComplexTPS(a::Real, tb::TPS, use::Descriptor) + ct = change(tb, use, type=ComplexTPS, scl2=im) + mad_ctpsa_seti!(ct.tpsa, Cint(0), convert(ComplexF64, 1), convert(ComplexF64, a)) + return ct +end + +function low_ComplexTPS(ta::TPS, tb::TPS, use::Union{TPS,ComplexTPS}) + return low_ComplexTPS(ta, tb, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa)))) +end + +function low_ComplexTPS(ta::TPS, b::Real, use::Union{TPS,ComplexTPS}) + return low_ComplexTPS(ta, b, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa)))) +end + +function low_ComplexTPS(a::Real, tb::TPS, use::Union{TPS,ComplexTPS}) + return low_ComplexTPS(a, tb, Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(use.tpsa)))) +end \ No newline at end of file diff --git a/src/utils.jl b/src/utils.jl new file mode 100644 index 00000000..5d556edb --- /dev/null +++ b/src/utils.jl @@ -0,0 +1,150 @@ +numtype(t::TPS) = Float64 +numtype(ct::ComplexTPS) = ComplexF64 +numtype(::Type{TPS}) = Float64 +numtype(::Type{ComplexTPS}) = ComplexF64 + +lowtype(t::TPS) = Ptr{RTPSA} +lowtype(ct::ComplexTPS) = Ptr{CTPSA} +lowtype(::Type{TPS}) = Ptr{RTPSA} +lowtype(::Type{ComplexTPS}) = Ptr{CTPSA} + +getdesc(t::Union{TPS,ComplexTPS}) = Descriptor(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)) +numvars(t::Union{TPS,ComplexTPS}) = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)).nv +numparams(t::Union{TPS,ComplexTPS}) = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)).np +numnn(t::Union{TPS,ComplexTPS}) = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d)).nn +getdesc(d::Descriptor) = d +numvars(d::Descriptor) = unsafe_load(d.desc).nv +numparams(d::Descriptor) = unsafe_load(d.desc).np +numnn(d::Descriptor) = unsafe_load(d.desc).nn +getdesc(d::Nothing) = nothing + + + +const SMIndexType = Union{Vector{<:Pair{<:Integer,<:Integer}}, Tuple{Vararg{Pair{<:Integer,<:Integer}}}} +const MIndexType = Union{Vector{<:Integer}, Tuple{Vararg{Integer}}} +const TPSIndexType = Union{Integer, + MIndexType, + SMIndexType} + + +cycle!(t::Ptr{RTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_::Ref{Cdouble}) = (@inline; mad_tpsa_cycle!(t, i, n, m_, v_)) +cycle!(t::Ptr{CTPSA}, i::Cint, n::Cint, m_::Vector{Cuchar}, v_::Ref{ComplexF64}) = (@inline; mad_ctpsa_cycle!(t, i, n, m_, v_)) + +# Generic function to make new copy of TPS with different descriptor +function change(t1::Union{TPS,ComplexTPS}, newd::Descriptor; type::Type=typeof(t1), scl2::Number=1) + # Quick check if actually changing + if Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d) == newd.desc + return type(t1) + end + + # THE NUMBER OF VARIABLES and PARAMETERS MUST AGREE!!! + unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)).nv == unsafe_load(newd.desc).nv || error("Number of variables in GTPSAs do not agree!") + unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)).np == unsafe_load(newd.desc).np || error("Number of parameters in GTPSAs do not agree!") + + t = type(use=newd) + change!(t, t1, 0, scl2) + return t +end + +function change!(t::Union{TPS,ComplexTPS},t1::Union{TPS,ComplexTPS}, scl1::Number=0, scl2::Number=1) + desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) + nv = desc.nv + np = desc.np + coef = Ref{numtype(t1)}() + mono = Vector{Cuchar}(undef, np+nv) + idx = cycle!(t1.tpsa, Cint(-1), np+nv, mono, coef) + while idx >= 0 + # if valid monomial in new descriptor: + if convert(Bool, mad_desc_isvalidm(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d), np+nv, mono)) + setm!(t.tpsa, np+nv, mono, convert(numtype(t), scl1), convert(numtype(t), scl2*coef[])) # set new tpsa + end + idx = cycle!(t1.tpsa, idx, np+nv, mono, coef) + end +end + +# Function to convert var=>ord, params=(param=>ord,) to low level sparse monomial format (varidx1, ord1, varidx2, ord2, paramidx, ordp1,...) +function pairs_to_sm(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}; params::Union{Vector{<:Pair{<:Integer,<:Integer}},Tuple{Vararg{<:Pair{<:Integer,<:Integer}}},Nothing}=nothing)::Tuple{Vector{Cint}, Cint} + # WE MUST Order THE VARIABLES !!! + nv = numvars(t) + numv = Cint(length(vars)) + if !isnothing(params) + nump = Cint(length(params)) + imin = min(minimum(x->x.first, vars,init=typemax(Int)), minimum(x->x.first+nv, params,init=typemax(Int))) + imax = max(maximum(x->x.first, vars,init=0), maximum(x->x.first+nv, params,init=0)) + else + nump = 0 + imin = minimum(x->x.first, vars,init=typemax(Int)) + imax = maximum(x->x.first, vars,init=0) + end + len = imax-imin+1 + sm = zeros(Cint, 2*len) + sm[1:2:end] = imin:imax + for i=1:numv + sm[2*(vars[i].first-imin+1)] = convert(Cint, vars[i].second) + end + for i=1:nump + sm[2*(params[i].first+nv-imin+1)] = convert(Cint, params[i].second) + end + + return sm, 2*len +end + +# Function to convert var=>ord, params=(param=>ord,) to monomial format (byte array of orders) +function pairs_to_m(t::Union{TPS,ComplexTPS}, vars::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}; params::Union{Vector{<:Pair{<:Integer, <:Integer}},Tuple{Vararg{Pair{<:Integer,<:Integer}}}}=Pair{Int,Int}[],zero_mono=true)::Tuple{Vector{UInt8}, Cint} + nv = numvars(t) + n = Cint(0) + if isempty(params) + n = Cint(maximum(map(x->x.first, vars))) + else + n = Cint(maximum(map(x->x.first, params))) + nv + end + if zero_mono + ords = zeros(Cuchar, n) + else + ords = ones(Cuchar, n).*0xff + end + for var in vars + ords[var.first] = convert(Cuchar, var.second) + end + for param in params + ords[nv + param.first] = convert(Cuchar, param.second) + end + return ords, n +end + +# Prevent undefined behavior +# Until AbstractComplex is implemented, I make the ctor return error because this should never happen +# asumming I wrapped enough +#= +Complex(t1::TPS) = complex(t1) +Complex(t1::TPS, t2::TPS) = complex(t1, t2) +Complex(t1::TPS, a::Real) = complex(t1, a) +Complex(a::Real, t1::TPS) = complex(a, t1) +Complex{TPS}(t1::TPS) = complex(t1) +Complex{TPS}(t1::TPS, t2::TPS) = complex(t1, t2) +Complex{TPS}(t1::TPS, a::Real) = complex(t1, a) +Complex{TPS}(a::Real, t1::TPS) = complex(a, t1)=# +Complex(t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex(t1::TPS, t2::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex(t1::TPS, a::Real) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex(a::Real, t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex{TPS}(t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex{TPS}(t1::TPS, t2::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex{TPS}(t1::TPS, a::Real) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") +Complex{TPS}(a::Real, t1::TPS) = error("ComplexTPS can only be defined as an AbstractComplex type (to be implemented in Julia PR #35587). If this error was reached without explicitly attempting to create a Complex{TPS}, please submit an issue to GTPSA.jl with an example.") + +promote_rule(::Type{TPS}, ::Type{T}) where {T<:Real} = TPS #::Union{Type{<:AbstractFloat}, Type{<:Integer}, Type{<:Rational}, Type{<:AbstractIrrational}}) = TPS +promote_rule(::Type{ComplexTPS}, ::Type{T}) where {T<:Number} = ComplexTPS #::Union{Type{Complex{<:Real}},Type{<:AbstractFloat}, Type{<:Integer}, Type{<:Rational}, Type{<:AbstractIrrational}}) = ComplexTPS +promote_rule(::Type{TPS}, ::Type{T}) where {T<:Number}= ComplexTPS + +# Handle bool which is special for some reason ++(t::TPS, z::Complex{Bool}) = t + Complex{Int}(z) ++(z::Complex{Bool}, t::TPS) = Complex{Int}(z) + t +-(t::TPS, z::Complex{Bool}) = t - Complex{Int}(z) +-(z::Complex{Bool}, t::TPS) = Complex{Int}(z) - t +*(t::TPS, z::Complex{Bool}) = t * Complex{Int}(z) +*(z::Complex{Bool}, t::TPS) = Complex{Int}(z) * t +/(t::TPS, z::Complex{Bool}) = t / Complex{Int}(z) +/(z::Complex{Bool}, t::TPS) = Complex{Int}(z) / t +^(t::TPS, z::Complex{Bool}) = t ^ Complex{Int}(z) +^(z::Complex{Bool}, t::TPS) = Complex{Int}(z) ^ t \ No newline at end of file diff --git a/test/compare_MAD.jl b/test/compare_MAD.jl index d88fbf4f..b8802296 100644 --- a/test/compare_MAD.jl +++ b/test/compare_MAD.jl @@ -1,13 +1,6 @@ # Julia script to compare current GTPSA.jl with latest # MAD_TPSA code from the MAD Git repo: # https://github.com/MethodicalAcceleratorDesign/MAD -# -# Known accepted disagreements: -# mad_ctpsa_equt: tol_ in GTPSA.jl is correct vs tol in mad_ctpsa.H -# mad_ctpsa_unit: C code has two equivalent function declarations with x and t. GTPSA.jl is correct -# mad_tpsa_ordv: Splats in Julia have names, C they do not, so script will show disagreements -# mad_ctpsa_ordv: Same as for mad_tpsa_ordv - using Downloads const io_out = IOBuffer() @@ -39,7 +32,7 @@ function compare(fun_decs_c, fun_decs_jl) names_jl = [x.name for x in funs_jl] #println.(names_jl) used = BitArray(undef, length(names_jl)) - + used .= 0 for fun_c in funs_c # println(io_out, "Checking $(fun_c.name)") if isempty(findall(x->x==fun_c.name, names_jl)) @@ -168,7 +161,11 @@ function get_c_fun_info(fun) continue end end - + + if isnothing(findfirst(" ", fun[1:curVarEnd])) + fun = strip(fun[curVarEnd+1:end]) + continue + end # Pointers in type will be added after parsing variable name type = fun[1:findfirst(" ", fun[1:curVarEnd])[1]-1] diff --git a/test/runtests.jl b/test/runtests.jl index 5c4c68bb..c90dd1c0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -136,9 +136,9 @@ import GTPSA: Desc, RTPSA, CTPSA # Now do operators # Test definition of 1-norm: tn = zero(t1) - tn[0] = 1; tn[1] = 2; tn[2] = 3; tn[3] = 4; tn[4] = 5; tn[5] = 6 + tn[0] = 1; tn[[1]] = 2; tn[[2]] = 3; tn[[3]] = 4; tn[[4]] = 5; tn[[5]] = 6 tcn = zero(ct1) - tcn[0] = 1+1im; tcn[1] = 2+2im; tcn[2] = 3+3im; tcn[3] = 4+4im; tcn[4] = 5+5im; tcn[5] = 6+6im + tcn[0] = 1+1im; tcn[[1]] = 2+2im; tcn[[2]] = 3+3im; tcn[[3]] = 4+4im; tcn[[4]] = 5+5im; tcn[[5]] = 6+6im @test norm(tn) == sum([i for i in 1:6]) @test norm(tcn) == sum([abs(i+i*im) for i in 1:6]) @@ -405,7 +405,7 @@ end @testset "Functions: identities, using TPSs" begin d = Descriptor(1, 5) t = TPS(use=d) - t[0] = 0.5; t[1] = 2; t[2] = 3; t[3] = 4; t[4] = 5; t[5] = 6 + t[0] = 0.5; t[[1]] = 2; t[[2]] = 3; t[[3]] = 4; t[[4]] = 5; t[[5]] = 6 tol = 1e-10 @@ -462,7 +462,7 @@ end @test norm(complex(t,t) - (t+im*t)) < tol t = ComplexTPS(t) - t[0] = 0.5+0.5im; t[1] = 2+2im; t[2] = 3+3im; t[3] = 4+4im; t[4] = 5+5im; t[5] = 6+6im + t[0] = 0.5+0.5im; t[[1]] = 2+2im; t[[2]] = 3+3im; t[[3]] = 4+4im; t[[4]] = 5+5im; t[[5]] = 6+6im @test norm(sin(t)^2+cos(t)^2 - 1) < tol @test norm(1/sin(t) - csc(t)) < tol @test norm(1/cos(t) - sec(t)) < tol @@ -522,216 +522,216 @@ end tol = 1e-18 f = sin(v[1]) - @test abs(f[0] - 0) < tol - @test abs(f[1] - 1) < tol - @test abs(f[2] - 0) < tol - @test abs(f[3] - -1/factorial(3)) < tol - @test abs(f[4] - 0) < tol - @test abs(f[5] - 1/factorial(5)) < tol - @test abs(f[6] - 0) < tol - @test abs(f[7] - -1/factorial(7)) < tol - @test abs(f[8] - 0) < tol - @test abs(f[9] - 1/factorial(9)) < tol - @test abs(f[10] - 0) < tol - - @test abs(f[1=>1] - f[1]) < tol - @test abs(f[1=>2] - f[2]) < tol - @test abs(f[1=>3] - f[3]) < tol - @test abs(f[1=>4] - f[4]) < tol - @test abs(f[1=>5] - f[5]) < tol - @test abs(f[1=>6] - f[6]) < tol - @test abs(f[1=>7] - f[7]) < tol - @test abs(f[1=>8] - f[8]) < tol - @test abs(f[1=>9] - f[9]) < tol - @test abs(f[1=>10] - f[10]) < tol + @test abs(f[[0]] - 0) < tol + @test abs(f[[1]] - 1) < tol + @test abs(f[[2]] - 0) < tol + @test abs(f[[3]] - -1/factorial(3)) < tol + @test abs(f[[4]] - 0) < tol + @test abs(f[[5]] - 1/factorial(5)) < tol + @test abs(f[[6]] - 0) < tol + @test abs(f[[7]] - -1/factorial(7)) < tol + @test abs(f[[8]] - 0) < tol + @test abs(f[[9]] - 1/factorial(9)) < tol + @test abs(f[[10]] - 0) < tol + + @test abs(f[[1=>1]] - f[[1]]) < tol + @test abs(f[[1=>2]] - f[[2]]) < tol + @test abs(f[[1=>3]] - f[[3]]) < tol + @test abs(f[[1=>4]] - f[[4]]) < tol + @test abs(f[[1=>5]] - f[[5]]) < tol + @test abs(f[[1=>6]] - f[[6]]) < tol + @test abs(f[[1=>7]] - f[[7]]) < tol + @test abs(f[[1=>8]] - f[[8]]) < tol + @test abs(f[[1=>9]] - f[[9]]) < tol + @test abs(f[[1=>10]] - f[[10]]) < tol fc = complex(f) - @test abs(fc[0] - 0) < tol - @test abs(fc[1] - 1) < tol - @test abs(fc[2] - 0) < tol - @test abs(fc[3] - -1/factorial(3)) < tol - @test abs(fc[4] - 0) < tol - @test abs(fc[5] - 1/factorial(5)) < tol - @test abs(fc[6] - 0) < tol - @test abs(fc[7] - -1/factorial(7)) < tol - @test abs(fc[8] - 0) < tol - @test abs(fc[9] - 1/factorial(9)) < tol - @test abs(fc[10] - 0) < tol - - @test abs(fc[1=>1] - f[1]) < tol - @test abs(fc[1=>2] - f[2]) < tol - @test abs(fc[1=>3] - f[3]) < tol - @test abs(fc[1=>4] - f[4]) < tol - @test abs(fc[1=>5] - f[5]) < tol - @test abs(fc[1=>6] - f[6]) < tol - @test abs(fc[1=>7] - f[7]) < tol - @test abs(fc[1=>8] - f[8]) < tol - @test abs(fc[1=>9] - f[9]) < tol - @test abs(fc[1=>10] - f[10]) < tol + @test abs(fc[[0]] - 0) < tol + @test abs(fc[[1]] - 1) < tol + @test abs(fc[[2]] - 0) < tol + @test abs(fc[[3]] - -1/factorial(3)) < tol + @test abs(fc[[4]] - 0) < tol + @test abs(fc[[5]] - 1/factorial(5)) < tol + @test abs(fc[[6]] - 0) < tol + @test abs(fc[[7]] - -1/factorial(7)) < tol + @test abs(fc[[8]] - 0) < tol + @test abs(fc[[9]] - 1/factorial(9)) < tol + @test abs(fc[[10]] - 0) < tol + + @test abs(fc[[1=>1]] - f[[1]]) < tol + @test abs(fc[[1=>2]] - f[[2]]) < tol + @test abs(fc[[1=>3]] - f[[3]]) < tol + @test abs(fc[[1=>4]] - f[[4]]) < tol + @test abs(fc[[1=>5]] - f[[5]]) < tol + @test abs(fc[[1=>6]] - f[[6]]) < tol + @test abs(fc[[1=>7]] - f[[7]]) < tol + @test abs(fc[[1=>8]] - f[[8]]) < tol + @test abs(fc[[1=>9]] - f[[9]]) < tol + @test abs(fc[[1=>10]] - f[[10]]) < tol f2 = sin(v[1]) + cos(v[2]) - @test abs(f2[0] - 1) < tol - @test abs(f2[1] - 1) < tol - @test abs(f2[2] - 0) < tol - @test abs(f2[3] - -1/factorial(3)) < tol - @test abs(f2[4] - 0) < tol - @test abs(f2[5] - 1/factorial(5)) < tol - @test abs(f2[6] - 0) < tol - @test abs(f2[7] - -1/factorial(7)) < tol - @test abs(f2[8] - 0) < tol - @test abs(f2[9] - 1/factorial(9)) < tol - @test abs(f2[10] - 0) < tol - - @test abs(f2[0,0] - 1) < tol - @test abs(f2[0,1] - 0) < tol - @test abs(f2[0,2] - -1/factorial(2)) < tol - @test abs(f2[0,3] - 0) < tol - @test abs(f2[0,4] - 1/factorial(4)) < tol - @test abs(f2[0,5] - 0) < tol - @test abs(f2[0,6] - -1/factorial(6)) < tol - @test abs(f2[0,7] - 0) < tol - @test abs(f2[0,8] - 1/factorial(8)) < tol - @test abs(f2[0,9] - 0) < tol - @test abs(f2[0,10] - -1/factorial(10)) < tol - - @test abs(f2[1=>1] - f2[1]) < tol - @test abs(f2[1=>2] - f2[2]) < tol - @test abs(f2[1=>3] - f2[3]) < tol - @test abs(f2[1=>4] - f2[4]) < tol - @test abs(f2[1=>5] - f2[5]) < tol - @test abs(f2[1=>6] - f2[6]) < tol - @test abs(f2[1=>7] - f2[7]) < tol - @test abs(f2[1=>8] - f2[8]) < tol - @test abs(f2[1=>9] - f2[9]) < tol - @test abs(f2[1=>10] - f2[10]) < tol - - @test abs(f2[2=>1] - f2[0,1]) < tol - @test abs(f2[2=>2] - f2[0,2]) < tol - @test abs(f2[2=>3] - f2[0,3]) < tol - @test abs(f2[2=>4] - f2[0,4]) < tol - @test abs(f2[2=>5] - f2[0,5]) < tol - @test abs(f2[2=>6] - f2[0,6]) < tol - @test abs(f2[2=>7] - f2[0,7]) < tol - @test abs(f2[2=>8] - f2[0,8]) < tol - @test abs(f2[2=>9] - f2[0,9]) < tol - @test abs(f2[2=>10] - f2[0,10]) < tol + @test abs(f2[[0]] - 1) < tol + @test abs(f2[[1]] - 1) < tol + @test abs(f2[[2]] - 0) < tol + @test abs(f2[[3]] - -1/factorial(3)) < tol + @test abs(f2[[4]] - 0) < tol + @test abs(f2[[5]] - 1/factorial(5)) < tol + @test abs(f2[[6]] - 0) < tol + @test abs(f2[[7]] - -1/factorial(7)) < tol + @test abs(f2[[8]] - 0) < tol + @test abs(f2[[9]] - 1/factorial(9)) < tol + @test abs(f2[[10]] - 0) < tol + + @test abs(f2[[0,0]] - 1) < tol + @test abs(f2[[0,1]] - 0) < tol + @test abs(f2[[0,2]] - -1/factorial(2)) < tol + @test abs(f2[[0,3]] - 0) < tol + @test abs(f2[[0,4]] - 1/factorial(4)) < tol + @test abs(f2[[0,5]] - 0) < tol + @test abs(f2[[0,6]] - -1/factorial(6)) < tol + @test abs(f2[[0,7]] - 0) < tol + @test abs(f2[[0,8]] - 1/factorial(8)) < tol + @test abs(f2[[0,9]] - 0) < tol + @test abs(f2[[0,10]] - -1/factorial(10)) < tol + + @test abs(f2[[1=>1]] - f2[[1]]) < tol + @test abs(f2[[1=>2]] - f2[[2]]) < tol + @test abs(f2[[1=>3]] - f2[[3]]) < tol + @test abs(f2[[1=>4]] - f2[[4]]) < tol + @test abs(f2[[1=>5]] - f2[[5]]) < tol + @test abs(f2[[1=>6]] - f2[[6]]) < tol + @test abs(f2[[1=>7]] - f2[[7]]) < tol + @test abs(f2[[1=>8]] - f2[[8]]) < tol + @test abs(f2[[1=>9]] - f2[[9]]) < tol + @test abs(f2[[1=>10]] - f2[[10]]) < tol + + @test abs(f2[[2=>1]] - f2[[0,1]]) < tol + @test abs(f2[[2=>2]] - f2[[0,2]]) < tol + @test abs(f2[[2=>3]] - f2[[0,3]]) < tol + @test abs(f2[[2=>4]] - f2[[0,4]]) < tol + @test abs(f2[[2=>5]] - f2[[0,5]]) < tol + @test abs(f2[[2=>6]] - f2[[0,6]]) < tol + @test abs(f2[[2=>7]] - f2[[0,7]]) < tol + @test abs(f2[[2=>8]] - f2[[0,8]]) < tol + @test abs(f2[[2=>9]] - f2[[0,9]]) < tol + @test abs(f2[[2=>10]] - f2[[0,10]]) < tol f2c = complex(sin(v[1]) + cos(v[2])) - @test abs(f2c[0] - 1) < tol - @test abs(f2c[1] - 1) < tol - @test abs(f2c[2] - 0) < tol - @test abs(f2c[3] - -1/factorial(3)) < tol - @test abs(f2c[4] - 0) < tol - @test abs(f2c[5] - 1/factorial(5)) < tol - @test abs(f2c[6] - 0) < tol - @test abs(f2c[7] - -1/factorial(7)) < tol - @test abs(f2c[8] - 0) < tol - @test abs(f2c[9] - 1/factorial(9)) < tol - @test abs(f2c[10] - 0) < tol - - @test abs(f2c[0,0] - 1) < tol - @test abs(f2c[0,1] - 0) < tol - @test abs(f2c[0,2] - -1/factorial(2)) < tol - @test abs(f2c[0,3] - 0) < tol - @test abs(f2c[0,4] - 1/factorial(4)) < tol - @test abs(f2c[0,5] - 0) < tol - @test abs(f2c[0,6] - -1/factorial(6)) < tol - @test abs(f2c[0,7] - 0) < tol - @test abs(f2c[0,8] - 1/factorial(8)) < tol - @test abs(f2c[0,9] - 0) < tol - @test abs(f2c[0,10] - -1/factorial(10)) < tol - - @test abs(f2c[1=>1] - f2c[1]) < tol - @test abs(f2c[1=>2] - f2c[2]) < tol - @test abs(f2c[1=>3] - f2c[3]) < tol - @test abs(f2c[1=>4] - f2c[4]) < tol - @test abs(f2c[1=>5] - f2c[5]) < tol - @test abs(f2c[1=>6] - f2c[6]) < tol - @test abs(f2c[1=>7] - f2c[7]) < tol - @test abs(f2c[1=>8] - f2c[8]) < tol - @test abs(f2c[1=>9] - f2c[9]) < tol - @test abs(f2c[1=>10] - f2c[10]) < tol - - @test abs(f2c[2=>1] - f2c[0,1]) < tol - @test abs(f2c[2=>2] - f2c[0,2]) < tol - @test abs(f2c[2=>3] - f2c[0,3]) < tol - @test abs(f2c[2=>4] - f2c[0,4]) < tol - @test abs(f2c[2=>5] - f2c[0,5]) < tol - @test abs(f2c[2=>6] - f2c[0,6]) < tol - @test abs(f2c[2=>7] - f2c[0,7]) < tol - @test abs(f2c[2=>8] - f2c[0,8]) < tol - @test abs(f2c[2=>9] - f2c[0,9]) < tol - @test abs(f2c[2=>10] - f2c[0,10]) < tol + @test abs(f2c[[0]] - 1) < tol + @test abs(f2c[[1]] - 1) < tol + @test abs(f2c[[2]] - 0) < tol + @test abs(f2c[[3]] - -1/factorial(3)) < tol + @test abs(f2c[[4]] - 0) < tol + @test abs(f2c[[5]] - 1/factorial(5)) < tol + @test abs(f2c[[6]] - 0) < tol + @test abs(f2c[[7]] - -1/factorial(7)) < tol + @test abs(f2c[[8]] - 0) < tol + @test abs(f2c[[9]] - 1/factorial(9)) < tol + @test abs(f2c[[10]] - 0) < tol + + @test abs(f2c[[0,0]] - 1) < tol + @test abs(f2c[[0,1]] - 0) < tol + @test abs(f2c[[0,2]] - -1/factorial(2)) < tol + @test abs(f2c[[0,3]] - 0) < tol + @test abs(f2c[[0,4]] - 1/factorial(4)) < tol + @test abs(f2c[[0,5]] - 0) < tol + @test abs(f2c[[0,6]] - -1/factorial(6)) < tol + @test abs(f2c[[0,7]] - 0) < tol + @test abs(f2c[[0,8]] - 1/factorial(8)) < tol + @test abs(f2c[[0,9]] - 0) < tol + @test abs(f2c[[0,10]] - -1/factorial(10)) < tol + + @test abs(f2c[[1=>1]] - f2c[[1]]) < tol + @test abs(f2c[[1=>2]] - f2c[[2]]) < tol + @test abs(f2c[[1=>3]] - f2c[[3]]) < tol + @test abs(f2c[[1=>4]] - f2c[[4]]) < tol + @test abs(f2c[[1=>5]] - f2c[[5]]) < tol + @test abs(f2c[[1=>6]] - f2c[[6]]) < tol + @test abs(f2c[[1=>7]] - f2c[[7]]) < tol + @test abs(f2c[[1=>8]] - f2c[[8]]) < tol + @test abs(f2c[[1=>9]] - f2c[[9]]) < tol + @test abs(f2c[[1=>10]] - f2c[[10]]) < tol + + @test abs(f2c[[2=>1]] - f2c[[0,1]]) < tol + @test abs(f2c[[2=>2]] - f2c[[0,2]]) < tol + @test abs(f2c[[2=>3]] - f2c[[0,3]]) < tol + @test abs(f2c[[2=>4]] - f2c[[0,4]]) < tol + @test abs(f2c[[2=>5]] - f2c[[0,5]]) < tol + @test abs(f2c[[2=>6]] - f2c[[0,6]]) < tol + @test abs(f2c[[2=>7]] - f2c[[0,7]]) < tol + @test abs(f2c[[2=>8]] - f2c[[0,8]]) < tol + @test abs(f2c[[2=>9]] - f2c[[0,9]]) < tol + @test abs(f2c[[2=>10]] - f2c[[0,10]]) < tol f3 = sin(v[1]) + cos(v[2]) + exp(p[1]) - @test abs(f3[0] - 2) < tol - @test abs(f3[1] - 1) < tol - @test abs(f3[2] - 0) < tol - @test abs(f3[3] - -1/factorial(3)) < tol - @test abs(f3[4] - 0) < tol - @test abs(f3[5] - 1/factorial(5)) < tol - @test abs(f3[6] - 0) < tol - @test abs(f3[7] - -1/factorial(7)) < tol - @test abs(f3[8] - 0) < tol - @test abs(f3[9] - 1/factorial(9)) < tol - @test abs(f3[10] - 0) < tol - - @test abs(f3[0,0] - 2) < tol - @test abs(f3[0,1] - 0) < tol - @test abs(f3[0,2] - -1/factorial(2)) < tol - @test abs(f3[0,3] - 0) < tol - @test abs(f3[0,4] - 1/factorial(4)) < tol - @test abs(f3[0,5] - 0) < tol - @test abs(f3[0,6] - -1/factorial(6)) < tol - @test abs(f3[0,7] - 0) < tol - @test abs(f3[0,8] - 1/factorial(8)) < tol - @test abs(f3[0,9] - 0) < tol - @test abs(f3[0,10] - -1/factorial(10)) < tol - - @test abs(f3[0,0,0,0] - 2) < tol - @test abs(f3[0,0,0,1] - 1/factorial(1)) < tol - @test abs(f3[0,0,0,2] - 1/factorial(2)) < tol - @test abs(f3[0,0,0,3] - 1/factorial(3)) < tol - @test abs(f3[0,0,0,4] - 1/factorial(4)) < tol - @test abs(f3[0,0,0,5] - 1/factorial(5)) < tol - @test abs(f3[0,0,0,6] - 1/factorial(6)) < tol - @test abs(f3[0,0,0,7] - 1/factorial(7)) < tol - @test abs(f3[0,0,0,8] - 1/factorial(8)) < tol - @test abs(f3[0,0,0,9] - 1/factorial(9)) < tol - @test abs(f3[0,0,0,10] - 1/factorial(10)) < tol - - @test abs(f3[1=>1] - f3[1]) < tol - @test abs(f3[1=>2] - f3[2]) < tol - @test abs(f3[1=>3] - f3[3]) < tol - @test abs(f3[1=>4] - f3[4]) < tol - @test abs(f3[1=>5] - f3[5]) < tol - @test abs(f3[1=>6] - f3[6]) < tol - @test abs(f3[1=>7] - f3[7]) < tol - @test abs(f3[1=>8] - f3[8]) < tol - @test abs(f3[1=>9] - f3[9]) < tol - @test abs(f3[1=>10] - f3[10]) < tol - - @test abs(f3[2=>1] - f3[0,1]) < tol - @test abs(f3[2=>2] - f3[0,2]) < tol - @test abs(f3[2=>3] - f3[0,3]) < tol - @test abs(f3[2=>4] - f3[0,4]) < tol - @test abs(f3[2=>5] - f3[0,5]) < tol - @test abs(f3[2=>6] - f3[0,6]) < tol - @test abs(f3[2=>7] - f3[0,7]) < tol - @test abs(f3[2=>8] - f3[0,8]) < tol - @test abs(f3[2=>9] - f3[0,9]) < tol - @test abs(f3[2=>10] - f3[0,10]) < tol - - @test abs(f3[params=[1=>1]] - f3[0,0,0,1]) < tol - @test abs(f3[params=[1=>2]] - f3[0,0,0,2]) < tol - @test abs(f3[params=[1=>3]] - f3[0,0,0,3]) < tol - @test abs(f3[params=[1=>4]] - f3[0,0,0,4]) < tol - @test abs(f3[params=[1=>5]] - f3[0,0,0,5]) < tol - @test abs(f3[params=[1=>6]] - f3[0,0,0,6]) < tol - @test abs(f3[params=[1=>7]] - f3[0,0,0,7]) < tol - @test abs(f3[params=[1=>8]] - f3[0,0,0,8]) < tol - @test abs(f3[params=[1=>9]] - f3[0,0,0,9]) < tol - @test abs(f3[params=[1=>10]] - f3[0,0,0,10]) < tol + @test abs(f3[[0]] - 2) < tol + @test abs(f3[[1]] - 1) < tol + @test abs(f3[[2]] - 0) < tol + @test abs(f3[[3]] - -1/factorial(3)) < tol + @test abs(f3[[4]] - 0) < tol + @test abs(f3[[5]] - 1/factorial(5)) < tol + @test abs(f3[[6]] - 0) < tol + @test abs(f3[[7]] - -1/factorial(7)) < tol + @test abs(f3[[8]] - 0) < tol + @test abs(f3[[9]] - 1/factorial(9)) < tol + @test abs(f3[[10]] - 0) < tol + + @test abs(f3[[0,0]] - 2) < tol + @test abs(f3[[0,1]] - 0) < tol + @test abs(f3[[0,2]] - -1/factorial(2)) < tol + @test abs(f3[[0,3]] - 0) < tol + @test abs(f3[[0,4]] - 1/factorial(4)) < tol + @test abs(f3[[0,5]] - 0) < tol + @test abs(f3[[0,6]] - -1/factorial(6)) < tol + @test abs(f3[[0,7]] - 0) < tol + @test abs(f3[[0,8]] - 1/factorial(8)) < tol + @test abs(f3[[0,9]] - 0) < tol + @test abs(f3[[0,10]] - -1/factorial(10)) < tol + + @test abs(f3[[0,0,0,0]] - 2) < tol + @test abs(f3[[0,0,0,1]] - 1/factorial(1)) < tol + @test abs(f3[[0,0,0,2]] - 1/factorial(2)) < tol + @test abs(f3[[0,0,0,3]] - 1/factorial(3)) < tol + @test abs(f3[[0,0,0,4]] - 1/factorial(4)) < tol + @test abs(f3[[0,0,0,5]] - 1/factorial(5)) < tol + @test abs(f3[[0,0,0,6]] - 1/factorial(6)) < tol + @test abs(f3[[0,0,0,7]] - 1/factorial(7)) < tol + @test abs(f3[[0,0,0,8]] - 1/factorial(8)) < tol + @test abs(f3[[0,0,0,9]] - 1/factorial(9)) < tol + @test abs(f3[[0,0,0,10]] - 1/factorial(10)) < tol + + @test abs(f3[[1=>1]] - f3[[1]]) < tol + @test abs(f3[[1=>2]] - f3[[2]]) < tol + @test abs(f3[[1=>3]] - f3[[3]]) < tol + @test abs(f3[[1=>4]] - f3[[4]]) < tol + @test abs(f3[[1=>5]] - f3[[5]]) < tol + @test abs(f3[[1=>6]] - f3[[6]]) < tol + @test abs(f3[[1=>7]] - f3[[7]]) < tol + @test abs(f3[[1=>8]] - f3[[8]]) < tol + @test abs(f3[[1=>9]] - f3[[9]]) < tol + @test abs(f3[[1=>10]] - f3[[10]]) < tol + + @test abs(f3[[2=>1]]- f3[[0,1]]) < tol + @test abs(f3[[2=>2]]- f3[[0,2]]) < tol + @test abs(f3[[2=>3]]- f3[[0,3]]) < tol + @test abs(f3[[2=>4]]- f3[[0,4]]) < tol + @test abs(f3[[2=>5]]- f3[[0,5]]) < tol + @test abs(f3[[2=>6]]- f3[[0,6]]) < tol + @test abs(f3[[2=>7]]- f3[[0,7]]) < tol + @test abs(f3[[2=>8]]- f3[[0,8]]) < tol + @test abs(f3[[2=>9]]- f3[[0,9]]) < tol + @test abs(f3[[2=>10]]- f3[[0,10]]) < tol + + @test abs(f3[params=[1=>1]] - f3[[0,0,0,1]]) < tol + @test abs(f3[params=[1=>2]] - f3[[0,0,0,2]]) < tol + @test abs(f3[params=[1=>3]] - f3[[0,0,0,3]]) < tol + @test abs(f3[params=[1=>4]] - f3[[0,0,0,4]]) < tol + @test abs(f3[params=[1=>5]] - f3[[0,0,0,5]]) < tol + @test abs(f3[params=[1=>6]] - f3[[0,0,0,6]]) < tol + @test abs(f3[params=[1=>7]] - f3[[0,0,0,7]]) < tol + @test abs(f3[params=[1=>8]] - f3[[0,0,0,8]]) < tol + @test abs(f3[params=[1=>9]] - f3[[0,0,0,9]]) < tol + @test abs(f3[params=[1=>10]] - f3[[0,0,0,10]]) < tol @@ -1037,7 +1037,7 @@ end @testset "@FastGTPSA - Functions: identities, using TPSs" begin d = Descriptor(1, 5) t = TPS(use=d) - t[0] = 0.5; t[1] = 2; t[2] = 3; t[3] = 4; t[4] = 5; t[5] = 6 + t[0] = 0.5; t[[1]] = 2; t[[2]] = 3; t[[3]] = 4; t[[4]] = 5; t[[5]] = 6 tol = 1e-10 @@ -1094,7 +1094,7 @@ end @test @FastGTPSA(norm(complex(t,t) - (t+im*t))) < tol t = ComplexTPS(t) - t[0] = 0.5+0.5im; t[1] = 2+2im; t[2] = 3+3im; t[3] = 4+4im; t[4] = 5+5im; t[5] = 6+6im + t[0] = 0.5+0.5im; t[[1]] = 2+2im; t[[2]] = 3+3im; t[[3]] = 4+4im; t[[4]] = 5+5im; t[[5]] = 6+6im @test @FastGTPSA(norm(sin(t)^2+cos(t)^2 - 1)) < tol @test @FastGTPSA(norm(1/sin(t) - csc(t))) < tol @test @FastGTPSA(norm(1/cos(t) - sec(t))) < tol @@ -1202,8 +1202,6 @@ end Comparing mad_tpsa.h to rtpsa.jl... mad_ctpsa.h downloaded. Comparing mad_ctpsa.h to ctpsa.jl... - mad_ctpsa_unit: Variable in C ctpsa_t* t => t::Ptr{CTPSA} not equal to Julia a::Ptr{CTPSA} - mad_ctpsa_unit: Variable in C ctpsa_t* r => r::Ptr{CTPSA} not equal to Julia c::Ptr{CTPSA} """ @test compare_MAD() == expected_out end diff --git a/test/type_stable.jl b/test/type_stable.jl index 4d5d2abd..c6c80a79 100644 --- a/test/type_stable.jl +++ b/test/type_stable.jl @@ -131,88 +131,89 @@ function type_stable_test() # Now do operators # Test definition of 1-norm: tn = zero(t1) - tn[0] = 1; tn[1] = 2; tn[2] = 3; tn[3] = 4; tn[4] = 5; tn[5] = 6 + tn[0] = 1; tn[[1]] = 2; tn[[2]] = 3; tn[[3]] = 4; tn[[4]] = 5; tn[[5]] = 6 tcn = zero(ct1) - tcn[0] = 1+1im; tcn[1] = 2+2im; tcn[2] = 3+3im; tcn[3] = 4+4im; tcn[4] = 5+5im; tcn[5] = 6+6im + tcn[0] = 1+1im; tcn[[1]] = 2+2im; tcn[[2]] = 3+3im; tcn[[3]] = 4+4im; tcn[[4]] = 5+5im; tcn[[5]] = 6+6im + norm(tn) == sum([i for i in 1:6]) norm(tcn) == sum([abs(i+i*im) for i in 1:6]) # TPS: - norm(t1 + t2 - t3) - norm(t2 + t1 - t3) - norm(t1 + 2 - t3) - norm(2 + t1 - t3) - norm(t3 - t2 - t1) - norm(t2 - t3 - -t1) - norm(t3 - 2 - t1) - norm(2 - t3 - -t1) - norm(t2 * t3 - 6) - norm(t3 * t2 - 6) - norm(t2 * 5 - 10) - norm(5 * t2 - 10 * t1) - norm(t1 / t2 - 1/2) - norm(t2 / t1 - 2) - norm(1 / t2 - 1/2) - norm(t2 / 3 - 2/3) - norm(t2 / t2 - t1) - norm(t2 / t2 - 1) - norm(t2 ^ t3 - 8) - norm(t3 ^ t2 - 9) - norm(t2 ^ 3 - 8) - norm(t2 ^ (1/2) - sqrt(2)) - norm(t2 ^ (1/2) - sqrt(t2)) - norm(2 ^ t3 - 8) - norm(inv(t3) - 1/t3) - norm(inv(t3) - 1/3) + norm(t1 + t2 - t3) < tol + norm(t2 + t1 - t3) < tol + norm(t1 + 2 - t3) < tol + norm(2 + t1 - t3) < tol + norm(t3 - t2 - t1) < tol + norm(t2 - t3 - -t1) < tol + norm(t3 - 2 - t1) < tol + norm(2 - t3 - -t1) < tol + norm(t2 * t3 - 6) < tol + norm(t3 * t2 - 6) < tol + norm(t2 * 5 - 10) < tol + norm(5 * t2 - 10 * t1) < tol + norm(t1 / t2 - 1/2) < tol + norm(t2 / t1 - 2) < tol + norm(1 / t2 - 1/2) < tol + norm(t2 / 3 - 2/3) < tol + norm(t2 / t2 - t1) < tol + norm(t2 / t2 - 1) < tol + norm(t2 ^ t3 - 8) < tol + norm(t3 ^ t2 - 9) < tol + norm(t2 ^ 3 - 8) < tol + norm(t2 ^ (1/2) - sqrt(2)) < tol + norm(t2 ^ (1/2) - sqrt(t2)) < tol + norm(2 ^ t3 - 8) < tol + norm(inv(t3) - 1/t3) < tol + norm(inv(t3) - 1/3) < tol # ComplexTPS: - norm(ct1 + ct2 - ct3) - norm(ct2 + ct1 - ct3) - norm(ct1 + (2+2im) - ct3) - norm((2+2im) + ct1 - ct3) - norm(ct3 - ct2 - ct1) - norm(ct2 - ct3 - -ct1) - norm(ct3 - (2+2im) - ct1) - norm((2+2im) - ct3 - -ct1) - norm(ct2 * ct3 - (2+2im)*(3+3im)) - norm(ct3 * ct2 - (2+2im)*(3+3im)) - norm(ct2 * 5 - (10+10im)) - norm(5 * ct2 - (10 * ct1)) - norm(ct1 / ct2 - (1+im)/(2+2im)) - norm(ct2 / ct1 - 2) - norm(1 / ct2 - 1/(2+2im)) - norm(ct2 / 3 - (2+2im)/3) - norm(ct2 / ct2 - 1) - norm(ct2 ^ ct3 - (2+2im)^(3+3im)) - norm(ct3 ^ ct2 - (3+3im)^(2+2im)) - norm(ct2 ^ 3 - (2+2im)^3) - norm(ct2 ^ (1/2) - sqrt(2+2im)) - norm(ct2 ^ (1/2) - sqrt(ct2)) - norm(2 ^ ct3 - 2^(3+3im)) - norm(inv(ct3) - 1/ct3) - norm(inv(ct3) - 1/(3+3im)) + norm(ct1 + ct2 - ct3) < tol + norm(ct2 + ct1 - ct3) < tol + norm(ct1 + (2+2im) - ct3) < tol + norm((2+2im) + ct1 - ct3) < tol + norm(ct3 - ct2 - ct1) < tol + norm(ct2 - ct3 - -ct1) < tol + norm(ct3 - (2+2im) - ct1) < tol + norm((2+2im) - ct3 - -ct1) < tol + norm(ct2 * ct3 - (2+2im)*(3+3im)) < tol + norm(ct3 * ct2 - (2+2im)*(3+3im)) < tol + norm(ct2 * 5 - (10+10im)) < tol + norm(5 * ct2 - (10 * ct1)) < tol + norm(ct1 / ct2 - (1+im)/(2+2im)) < tol + norm(ct2 / ct1 - 2) < tol + norm(1 / ct2 - 1/(2+2im)) < tol + norm(ct2 / 3 - (2+2im)/3) < tol + norm(ct2 / ct2 - 1) < tol + norm(ct2 ^ ct3 - (2+2im)^(3+3im)) < tol + norm(ct3 ^ ct2 - (3+3im)^(2+2im)) < tol + norm(ct2 ^ 3 - (2+2im)^3) < tol + norm(ct2 ^ (1/2) - sqrt(2+2im)) < tol + norm(ct2 ^ (1/2) - sqrt(ct2)) < tol + norm(2 ^ ct3 - 2^(3+3im)) < tol + norm(inv(ct3) - 1/ct3) < tol + norm(inv(ct3) - 1/(3+3im)) < tol # Promotion of TPS to ComplexTPS - norm(t1 + ct2 - (1 + (2+2im))) - norm(ct2 + t1 - (1 + (2+2im))) - norm(t1 + (2+2im) - (1 + (2+2im))) - norm((2+2im) + t1 - (1 + (2+2im))) - norm(t3 - ct2 - (3 - (2+2im))) - norm(ct2 - t3 - ((2+2im) - 3)) - norm(t3 - (2+2im) - (3 - (2+2im))) - norm((2+2im) - t3 - ((2+2im) - 3)) - norm(t2 * ct3 - 2 * (3+3im)) - norm(ct3 * t2 - 2 * (3+3im)) - norm(t2 * (3+3im) - 2 * (3+3im)) - norm((3+3im) * t2 - 2 * (3+3im)) - norm(t2 / ct3 - 2/(3+3im)) - norm(ct3 / t2 - (3+3im)/2) - norm(t2 / (3+3im) - 2/(3+3im)) - norm((3+3im) / t2 - (3+3im)/2) - norm(t2 ^ ct3 - 2^(3+3im)) - norm(ct3 ^ t2 - (3+3im)^2) - norm(t2 ^ (3+3im) - 2^(3+3im)) - norm((3+3im)^t2 - (3+3im)^2) + norm(t1 + ct2 - (1 + (2+2im))) < tol + norm(ct2 + t1 - (1 + (2+2im))) < tol + norm(t1 + (2+2im) - (1 + (2+2im))) < tol + norm((2+2im) + t1 - (1 + (2+2im))) < tol + norm(t3 - ct2 - (3 - (2+2im))) < tol + norm(ct2 - t3 - ((2+2im) - 3)) < tol + norm(t3 - (2+2im) - (3 - (2+2im))) < tol + norm((2+2im) - t3 - ((2+2im) - 3)) < tol + norm(t2 * ct3 - 2 * (3+3im)) < tol + norm(ct3 * t2 - 2 * (3+3im)) < tol + norm(t2 * (3+3im) - 2 * (3+3im)) < tol + norm((3+3im) * t2 - 2 * (3+3im)) < tol + norm(t2 / ct3 - 2/(3+3im)) < tol + norm(ct3 / t2 - (3+3im)/2) < tol + norm(t2 / (3+3im) - 2/(3+3im)) < tol + norm((3+3im) / t2 - (3+3im)/2) < tol + norm(t2 ^ ct3 - 2^(3+3im)) < tol + norm(ct3 ^ t2 - (3+3im)^2) < tol + norm(t2 ^ (3+3im) - 2^(3+3im)) < tol + norm((3+3im)^t2 - (3+3im)^2) < tol d = Descriptor(1, 5) t = TPS(use=d) @@ -227,75 +228,78 @@ function type_stable_test() t3[0] = 3 - norm(abs(-t) - abs(-v) ) - norm(sqrt(t) - sqrt(v)) - norm(exp(t) - exp(v)) - norm(log(t) - log(v)) - norm(sin(t) - sin(v)) - norm(cos(t) - cos(v)) - norm(tan(t) - tan(v)) - norm(csc(t) - csc(v)) - norm(sec(t) - sec(v)) - norm(cot(t) - cot(v)) - norm(sinc(t) - sinc(v)) - norm(sinh(t) - sinh(v)) - norm(cosh(t) - cosh(v)) - norm(tanh(t) - tanh(v)) - norm(csch(t) - csch(v)) - norm(sech(t) - sech(v)) - norm(coth(t) - coth(v)) - norm(asin(t) - asin(v)) - norm(acos(t) - acos(v)) - norm(atan(t) - atan(v)) - norm(acsc(1/t) - acsc(1/v)) - norm(asec(1/t) - asec(1/v)) - norm(acot(1/t) - acot(1/v)) - norm(asinh(t) - asinh(v)) - norm(acosh(1/t) - acosh(1/v)) - norm(atanh(t) - atanh(v)) - norm(acsch(1/t) - acsch(1/v)) - norm(asech(t) - asech(v)) - norm(acoth(1/t) - acoth(1/v)) - norm(asinc(t/pi) - asin(v)/(v)) - norm(asinhc(t/pi) - asinh(v)/(v)) - norm(zero(t) - zero(v)) - norm(real(t) - real(v)) - norm(imag(t) - imag(v)) - norm(conj(t) - conj(v)) - norm(sinhc(t/pi) - sinh(v)/v) - norm(erf(t) - erf(v)) - norm(erfc(t) - erfc(v)) - norm(-im*erf(t*im) - erfi(v)) - norm(atan(t3,t2) - atan(3,2)) - norm(atan(t3,2) - atan(3,2)) - norm(atan(3,t2) - atan(3,2)) - norm(atan(t3,-t2) - atan(3,-2)) - norm(atan(t3,-2) - atan(3,-2)) - norm(atan(3,-t2) - atan(3,-2)) - norm(atan(-t3,-t2) - atan(-3,-2)) - norm(atan(-t3,-2) - atan(-3,-2)) - norm(atan(-3,-t2) - atan(-3,-2)) - norm(atan(-t3,t2) - atan(-3,2)) - norm(atan(-t3,2) - atan(-3,2)) - norm(atan(-3,t2) - atan(-3,2)) - norm(hypot(t2,t3) - hypot(2,3)) - norm(hypot(2,t3) - hypot(2,3)) - norm(hypot(t2,3) - hypot(2,3)) - norm(hypot(t1,t2,t3) - hypot(1,2,3)) - norm(hypot(1, t2, t3) - hypot(1,2,3)) - norm(hypot(t1, 2, t3) - hypot(1,2,3)) - norm(hypot(t1, t2, 3) - hypot(1,2,3)) - norm(hypot(1, 2, t3) - hypot(1,2,3)) - norm(hypot(1, t2, 3) - hypot(1,2,3)) - norm(hypot(t1, 2, 3) - hypot(1,2,3)) - norm(angle(t2) - angle(2)) - norm(angle(-t2) - angle(-2)) - norm(complex(t3) - complex(3)) - norm(complex(t2,t3) - complex(2,3)) - norm(polar(t2) - (abs(2)+im*atan(0,2))) - norm(polar(-t1) - (abs(-1)+im*atan(0,-1))) - norm(rect(t2) - (2*cos(0) + 2*sin(0))) - norm(rect(-t1) - (-1*cos(0) + -1*sin(0))) + norm(abs(-t) - abs(-v) ) < tol + norm(sqrt(t) - sqrt(v)) < tol + norm(exp(t) - exp(v)) < tol + norm(log(t) - log(v)) < tol + norm(sin(t) - sin(v)) < tol + norm(cos(t) - cos(v)) < tol + norm(tan(t) - tan(v)) < tol + norm(csc(t) - csc(v)) < tol + norm(sec(t) - sec(v)) < tol + norm(cot(t) - cot(v)) < tol + norm(sinc(t) - sinc(v)) < tol + norm(sinh(t) - sinh(v)) < tol + norm(cosh(t) - cosh(v)) < tol + norm(tanh(t) - tanh(v)) < tol + norm(csch(t) - csch(v)) < tol + norm(sech(t) - sech(v)) < tol + norm(coth(t) - coth(v)) < tol + norm(asin(t) - asin(v)) < tol + norm(acos(t) - acos(v)) < tol + norm(atan(t) - atan(v)) < tol + norm(acsc(1/t) - acsc(1/v)) < tol + norm(asec(1/t) - asec(1/v)) < tol + norm(acot(1/t) - acot(1/v)) < tol + norm(asinh(t) - asinh(v)) < tol + norm(acosh(1/t) - acosh(1/v)) < tol + norm(atanh(t) - atanh(v)) < tol + norm(acsch(1/t) - acsch(1/v)) < tol + norm(asech(t) - asech(v)) < tol + norm(acoth(1/t) - acoth(1/v)) < tol + norm(asinc(t/pi) - asin(v)/(v)) < tol + norm(asinhc(t/pi) - asinh(v)/(v)) < tol + norm(zero(t) - zero(v)) < tol + norm(real(t) - real(v)) < tol + norm(imag(t) - imag(v)) < tol + norm(conj(t) - conj(v)) < tol + norm(sinhc(t/pi) - sinh(v)/v) < tol + norm(erf(t) - erf(v)) < tol + norm(erfc(t) - erfc(v)) < tol + norm(-im*erf(t*im) - erfi(v)) < tol + + norm(atan(t3,t2) - atan(3,2)) < tol + norm(atan(t3,2) - atan(3,2)) < tol + norm(atan(3,t2) - atan(3,2)) < tol + norm(atan(t3,-t2) - atan(3,-2)) < tol + norm(atan(t3,-2) - atan(3,-2)) < tol + norm(atan(3,-t2) - atan(3,-2)) < tol + norm(atan(-t3,-t2) - atan(-3,-2)) < tol + norm(atan(-t3,-2) - atan(-3,-2)) < tol + norm(atan(-3,-t2) - atan(-3,-2)) < tol + norm(atan(-t3,t2) - atan(-3,2)) < tol + norm(atan(-t3,2) - atan(-3,2)) < tol + norm(atan(-3,t2) - atan(-3,2)) < tol + + norm(hypot(t2,t3) - hypot(2,3)) < tol + norm(hypot(2,t3) - hypot(2,3)) < tol + norm(hypot(t2,3) - hypot(2,3)) < tol + norm(hypot(t1,t2,t3) - hypot(1,2,3)) < tol + norm(hypot(1, t2, t3) - hypot(1,2,3)) < tol + norm(hypot(t1, 2, t3) - hypot(1,2,3)) < tol + norm(hypot(t1, t2, 3) - hypot(1,2,3)) < tol + norm(hypot(1, 2, t3) - hypot(1,2,3)) < tol + norm(hypot(1, t2, 3) - hypot(1,2,3)) < tol + norm(hypot(t1, 2, 3) - hypot(1,2,3)) < tol + norm(angle(t2) - angle(2)) < tol + norm(angle(-t2) - angle(-2)) < tol + norm(complex(t3) - complex(3)) < tol + norm(complex(t2,t3) - complex(2,3)) < tol + norm(polar(t2) - (abs(2)+im*atan(0,2))) < tol + norm(polar(-t1) - (abs(-1)+im*atan(0,-1))) < tol + norm(rect(t2) - (2*cos(0) + im*2*sin(0))) < tol + norm(rect(-t1) - (-1*cos(0) + im*-1*sin(0))) < tol + v = 0.5+0.5im t = ComplexTPS(t) @@ -306,196 +310,200 @@ function type_stable_test() ct2[0] = 2 + 2im ct3 = zero(ct1) ct3[0] = 3 + 3im - norm(abs(-t) - abs(-v) ) - norm(sqrt(t) - sqrt(v)) - norm(exp(t) - exp(v)) - norm(log(t) - log(v)) - norm(sin(t) - sin(v)) - norm(cos(t) - cos(v)) - norm(tan(t) - tan(v)) - norm(csc(t) - csc(v)) - norm(sec(t) - sec(v)) - norm(cot(t) - cot(v)) - norm(sinc(t) - sinc(v)) - norm(sinh(t) - sinh(v)) - norm(cosh(t) - cosh(v)) - norm(tanh(t) - tanh(v)) - norm(csch(t) - csch(v)) - norm(sech(t) - sech(v)) - norm(coth(t) - coth(v)) - norm(asin(t) - asin(v)) - norm(acos(t) - acos(v)) - norm(atan(t) - atan(v)) - norm(acsc(t) - acsc(v)) - norm(asec(t) - asec(v)) - norm(acot(t) - acot(v)) - norm(asinh(t) - asinh(v)) - norm(acosh(t) - acosh(v)) - norm(atanh(t) - atanh(v)) - norm(acsch(t) - acsch(v)) - norm(asech(t) - asech(v)) - norm(acoth(t) - acoth(v)) - norm(asinc(t) - asin(v)/v) - norm(asinhc(t) - asinh(v)/v) - norm(zero(t) - zero(v)) - norm(real(t) - real(v)) - norm(imag(t) - imag(v)) - norm(conj(t) - conj(v)) - norm(sinhc(t/pi) - sinh(v)/v) - norm(erf(t) - erf(v)) - norm(erfc(t) - erfc(v)) - norm(-im*erf(t*im) - erfi(v)) - norm(hypot(ct2,ct3) - hypot(2+2im,3+3im)) - norm(hypot(2+2im,ct3) - hypot(2+2im,3+3im)) - norm(hypot(ct2,3+3im) - hypot(2+2im,3+3im)) - norm(hypot(ct1,ct2,ct3) - hypot(1+1im,2+2im,3+3im)) - norm(hypot(1+1im, ct2, ct3) - hypot(1+1im,2+2im,3+3im)) - norm(hypot(ct1, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im)) - norm(hypot(ct1, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im)) - norm(hypot(1+1im, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im)) - norm(hypot(1+1im, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im)) - norm(hypot(ct1, 2+2im, 3+3im) - hypot(1+1im,2+2im,3+3im)) - norm(angle(t2+im*t3) - angle(2+3im)) - norm(angle(t2-im*t3) - angle(2-3im)) - norm(angle(-t2-im*t3) - angle(-2-3im)) - norm(angle(-t2+im*t3) - angle(-2+3im)) - norm(angle(ct2) - angle(2+2im)) - norm(angle(-ct2) - angle(-2-2im)) - norm(complex(ct3) - complex(3+3im)) - norm(polar(ct2) - (abs(2+2im)+im*angle(2+2im))) - norm(polar(-ct1) - (abs(-1-im)+im*angle(-1-im))) - norm(rect(ct2) - (2*cos(2) + 2*sin(2))) - norm(rect(-ct1) - (-1*cos(-1) + -1*sin(-1))) + norm(abs(-t) - abs(-v) ) < tol + norm(sqrt(t) - sqrt(v)) < tol + norm(exp(t) - exp(v)) < tol + norm(log(t) - log(v)) < tol + norm(sin(t) - sin(v)) < tol + norm(cos(t) - cos(v)) < tol + norm(tan(t) - tan(v)) < tol + norm(csc(t) - csc(v)) < tol + norm(sec(t) - sec(v)) < tol + norm(cot(t) - cot(v)) < tol + norm(sinc(t) - sinc(v)) < tol + norm(sinh(t) - sinh(v)) < tol + norm(cosh(t) - cosh(v)) < tol + norm(tanh(t) - tanh(v)) < tol + norm(csch(t) - csch(v)) < tol + norm(sech(t) - sech(v)) < tol + norm(coth(t) - coth(v)) < tol + + norm(asin(t) - asin(v)) < tol + norm(acos(t) - acos(v)) < tol + norm(atan(t) - atan(v)) < tol + norm(acsc(t) - acsc(v)) < tol + norm(asec(t) - asec(v)) < tol + norm(acot(t) - acot(v)) < tol + norm(asinh(t) - asinh(v)) < tol + norm(acosh(t) - acosh(v)) < tol + norm(atanh(t) - atanh(v)) < tol + norm(acsch(t) - acsch(v)) < tol + norm(asech(t) - asech(v)) < tol + norm(acoth(t) - acoth(v)) < tol + norm(asinc(t/pi) - asin(v)/v) < tol + norm(asinhc(t/pi) - asinh(v)/v) < tol + + norm(zero(t) - zero(v)) < tol + norm(real(t) - real(v)) < tol + norm(imag(t) - imag(v)) < tol + norm(conj(t) - conj(v)) < tol + norm(sinhc(t/pi) - sinh(v)/v) < tol + norm(erf(t) - erf(v)) < tol + norm(erfc(t) - erfc(v)) < tol + norm(-im*erf(t*im) - erfi(v)) < tol + norm(hypot(ct2,ct3) - hypot(2+2im,3+3im)) < tol + norm(hypot(2+2im,ct3) - hypot(2+2im,3+3im)) < tol + norm(hypot(ct2,3+3im) - hypot(2+2im,3+3im)) < tol + norm(hypot(ct1,ct2,ct3) - hypot(1+1im,2+2im,3+3im)) < tol + norm(hypot(1+1im, ct2, ct3) - hypot(1+1im,2+2im,3+3im)) < tol + norm(hypot(ct1, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im)) < tol + norm(hypot(ct1, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im)) < tol + norm(hypot(1+1im, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im)) < tol + norm(hypot(1+1im, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im)) < tol + norm(hypot(ct1, 2+2im, 3+3im) - hypot(1+1im,2+2im,3+3im)) < tol + + norm(angle(t2+im*t3) - angle(2+3im)) < tol + norm(angle(t2-im*t3) - angle(2-3im)) < tol + norm(angle(-t2-im*t3) - angle(-2-3im)) < tol + norm(angle(-t2+im*t3) - angle(-2+3im)) < tol + norm(angle(ct2) - angle(2+2im)) < tol + norm(angle(-ct2) - angle(-2-2im)) < tol + norm(complex(ct3) - complex(3+3im)) < tol + norm(polar(ct2) - (abs(2+2im)+im*angle(2+2im))) < tol + norm(polar(-ct1) - (abs(-1-im)+im*angle(-1-im))) < tol + norm(rect(ct2) - (2*cos(2) + im*2*sin(2))) < tol + norm(rect(-ct1) - (-1*cos(-1) + im*-1*sin(-1))) < tol + # Hypot, mixing TPS with ComplexTPS - norm(hypot(ct1, ct2, t3) - hypot(1+1im,2+2im,3)) - norm(hypot(ct1, t2, ct3) - hypot(1+1im,2,3+3im)) - norm(hypot(t1, ct2, ct3) - hypot(1,2+2im,3+3im)) - norm(hypot(ct1, t2, t3) - hypot(1+1im,2,3)) - norm(hypot(t1, ct2, t3) - hypot(1,2+2im,3)) - norm(hypot(t1, t2, ct3) - hypot(1,2,3+3im)) - norm(hypot(ct1,t2,3+3im) - hypot(1+1im,2,3+3im)) - norm(hypot(t1, ct2, 3+3im) - hypot(1,2+2im,3+3im)) - norm(hypot(ct1,2+2im,t3) - hypot(1+1im,2+2im,3)) - norm(hypot(t1,2+2im,ct3) - hypot(1,2+2im,3+3im)) - norm(hypot(1+1im,ct2,t3) - hypot(1+1im,2+2im,3)) - norm(hypot(1+1im, t2, ct3) - hypot(1+1im,2,3+3im)) - norm(hypot(t1,t2,3+3im) - hypot(1,2,3+3im)) - norm(hypot(t1,2+2im,t3) - hypot(1,2+2im,3)) - norm(hypot(1+1im,t2,t3) - hypot(1+1im,2,3)) - norm(hypot(t1,2,3+3im) - hypot(1,2,3+3im)) - norm(hypot(1,t2,3+3im) - hypot(1,2,3+3im)) - norm(hypot(1+1im,2,t3) - hypot(1+1im,2,3)) + norm(hypot(ct1, ct2, t3) - hypot(1+1im,2+2im,3)) < tol + norm(hypot(ct1, t2, ct3) - hypot(1+1im,2,3+3im)) < tol + norm(hypot(t1, ct2, ct3) - hypot(1,2+2im,3+3im)) < tol + norm(hypot(ct1, t2, t3) - hypot(1+1im,2,3)) < tol + norm(hypot(t1, ct2, t3) - hypot(1,2+2im,3)) < tol + norm(hypot(t1, t2, ct3) - hypot(1,2,3+3im)) < tol + norm(hypot(ct1,t2,3+3im) - hypot(1+1im,2,3+3im)) < tol + norm(hypot(t1, ct2, 3+3im) - hypot(1,2+2im,3+3im)) < tol + norm(hypot(ct1,2+2im,t3) - hypot(1+1im,2+2im,3)) < tol + norm(hypot(t1,2+2im,ct3) - hypot(1,2+2im,3+3im)) < tol + norm(hypot(1+1im,ct2,t3) - hypot(1+1im,2+2im,3)) < tol + norm(hypot(1+1im, t2, ct3) - hypot(1+1im,2,3+3im)) < tol + norm(hypot(t1,t2,3+3im) - hypot(1,2,3+3im)) < tol + norm(hypot(t1,2+2im,t3) - hypot(1,2+2im,3)) < tol + norm(hypot(1+1im,t2,t3) - hypot(1+1im,2,3)) < tol + norm(hypot(t1,2,3+3im) - hypot(1,2,3+3im)) < tol + norm(hypot(1,t2,3+3im) - hypot(1,2,3+3im)) < tol + norm(hypot(1+1im,2,t3) - hypot(1+1im,2,3)) < tol d = Descriptor(1, 5) t = TPS(use=d) - t[0] = 0.5; t[1] = 2; t[2] = 3; t[3] = 4; t[4] = 5; t[5] = 6 + t[0] = 0.5; t[[1]] = 2; t[[2]] = 3; t[[3]] = 4; t[[4]] = 5; t[[5]] = 6 tol = 1e-10 - norm(sin(t)^2+cos(t)^2 - 1) - norm(1/sin(t) - csc(t)) - norm(1/cos(t) - sec(t)) - norm(1/tan(t) - cot(t)) - norm(sin(t)/cos(t) - tan(t)) - norm(cos(2*t) - cos(t)^2 + sin(t)^2) - norm(sec(t)^2 - 1 - tan(t)^2) - norm(sin(t/2) - sqrt((1-cos(t))/2)) - norm(cos(t/2) - sqrt((1+cos(t))/2)) - norm(sqrt(t^2) - abs(t)) - norm(csc(t)^2 - cot(t)^2 - 1) - norm(exp(log(t)) - t) - norm(log(exp(t)) - t) - norm(log(exp(t)) - exp(log(t))) - norm(log(t^2) - 2*log(t)) - norm(5*log(t) - log(t^5)) - norm(t*log(5) - log(5^t)) - norm(sinc(t) - sin(pi*t)/(pi*t)) - norm(sinhc(t/pi) - sinh(t)/t) - norm(exp(im*t) - cos(t) - im*sin(t)) - norm(real(exp(im*t)) - cos(t)) - norm(imag(exp(im*t)) - sin(t)) - norm(sinh(t) - (exp(t) - exp(-t))/2) - norm(cosh(t) - (exp(t) + exp(-t))/2) - norm(tanh(t) - sinh(t)/cosh(t)) - norm(csch(t) - 1/sinh(t)) - norm(sech(t) - 1/cosh(t)) - norm(coth(t) - cosh(t)/sinh(t)) - norm(coth(t) - 1/tanh(t)) - norm(cosh(t)^2 - sinh(t)^2 - 1) - norm(1 - tanh(t)^2 - sech(t)^2) - norm(coth(t)^2 - 1 - csch(t)^2) - norm(asin(sin(t)) - t) - norm(acos(cos(t)) - t) - norm(atan(tan(t)) - t) - norm(acsc(1/t) - asin(t)) - norm(asec(1/t) - acos(t)) - norm(acot(1/t) - atan(t)) - norm(asinh(sinh(t)) - t) - norm(acosh(cosh(t)) - t) - norm(atanh(tanh(t)) - t) - norm(acsch(t) - asinh(1/t)) - norm(asech(t) - acosh(1/t)) - norm(acoth(1/t) - atanh(t)) - norm(asinc(t/pi) - asin(t)/t) - norm(asinhc(t/pi) - asinh(t)/t) - norm(erfc(t) - 1 + erf(t)) - norm(erf(-t) + erf(t)) - norm(angle(t)) - norm(complex(t) - t) - norm(complex(t,t) - (t+im*t)) + norm(sin(t)^2+cos(t)^2 - 1) < tol + norm(1/sin(t) - csc(t)) < tol + norm(1/cos(t) - sec(t)) < tol + norm(1/tan(t) - cot(t)) < tol + norm(sin(t)/cos(t) - tan(t)) < tol + norm(cos(2*t) - cos(t)^2 + sin(t)^2) < tol + norm(sec(t)^2 - 1 - tan(t)^2) < tol + norm(sin(t/2) - sqrt((1-cos(t))/2)) < tol + norm(cos(t/2) - sqrt((1+cos(t))/2)) < tol + norm(sqrt(t^2) - abs(t)) < tol + norm(csc(t)^2 - cot(t)^2 - 1) < tol + norm(exp(log(t)) - t) < tol + norm(log(exp(t)) - t) < tol + norm(log(exp(t)) - exp(log(t))) < tol + norm(log(t^2) - 2*log(t)) < tol + norm(5*log(t) - log(t^5)) < tol + norm(t*log(5) - log(5^t)) < tol + norm(sinc(t) - sin(pi*t)/(pi*t)) < tol + norm(sinhc(t/pi) - sinh(t)/t) < tol + norm(exp(im*t) - cos(t) - im*sin(t)) < tol + norm(real(exp(im*t)) - cos(t)) < tol + norm(imag(exp(im*t)) - sin(t)) < tol + norm(sinh(t) - (exp(t) - exp(-t))/2) < tol + norm(cosh(t) - (exp(t) + exp(-t))/2) < tol + norm(tanh(t) - sinh(t)/cosh(t)) < tol + norm(csch(t) - 1/sinh(t)) < tol + norm(sech(t) - 1/cosh(t)) < tol + norm(coth(t) - cosh(t)/sinh(t)) < tol + norm(coth(t) - 1/tanh(t)) < tol + norm(cosh(t)^2 - sinh(t)^2 - 1) < tol + norm(1 - tanh(t)^2 - sech(t)^2) < tol + norm(coth(t)^2 - 1 - csch(t)^2) < tol + norm(asin(sin(t)) - t) < tol + norm(acos(cos(t)) - t) < tol + norm(atan(tan(t)) - t) < tol + norm(acsc(1/t) - asin(t)) < tol + norm(asec(1/t) - acos(t)) < tol + norm(acot(1/t) - atan(t)) < tol + norm(asinh(sinh(t)) - t) < tol + norm(acosh(cosh(t)) - t) < tol + norm(atanh(tanh(t)) - t) < tol + norm(acsch(t) - asinh(1/t)) < tol + norm(asech(t) - acosh(1/t)) < tol + norm(acoth(1/t) - atanh(t)) < tol + norm(asinc(t/pi) - asin(t)/t) < tol + norm(asinhc(t/pi) - asinh(t)/t) < tol + norm(erfc(t) - 1 + erf(t)) < tol + norm(erf(-t) + erf(t)) < tol + norm(angle(t)) < tol + norm(complex(t) - t) < tol + norm(complex(t,t) - (t+im*t)) < tol t = ComplexTPS(t) - t[0] = 0.5+0.5im; t[1] = 2+2im; t[2] = 3+3im; t[3] = 4+4im; t[4] = 5+5im; t[5] = 6+6im - norm(sin(t)^2+cos(t)^2 - 1) - norm(1/sin(t) - csc(t)) - norm(1/cos(t) - sec(t)) - norm(1/tan(t) - cot(t)) - norm(sin(t)/cos(t) - tan(t)) - norm(cos(2*t) - cos(t)^2 + sin(t)^2) - norm(sec(t)^2 - 1 - tan(t)^2) - norm(sin(t/2) - sqrt((1-cos(t))/2)) - norm(cos(t/2) - sqrt((1+cos(t))/2)) - norm(sqrt(t^2) - t) - norm(csc(t)^2 - cot(t)^2 - 1) - norm(exp(log(t)) - t) - norm(log(exp(t)) - t) - norm(log(exp(t)) - exp(log(t))) - norm(log(t^2) - 2*log(t)) - norm(5*log(t) - log(t^5) - 2*pi*im) - norm(t*log(5) - log(5^t)) - norm(sinc(t/pi) - sin(t)/t) - norm(sinhc(t/pi) - sinh(t)/t) - norm(exp(im*t) - cos(t) - im*sin(t)) - norm(sinh(t) - (exp(t) - exp(-t))/2) - norm(cosh(t) - (exp(t) + exp(-t))/2) - norm(tanh(t) - sinh(t)/cosh(t)) - norm(csch(t) - 1/sinh(t)) - norm(sech(t) - 1/cosh(t)) - norm(coth(t) - cosh(t)/sinh(t)) - norm(coth(t) - 1/tanh(t)) - norm(cosh(t)^2 - sinh(t)^2 - 1) - norm(1 - tanh(t)^2 - sech(t)^2) - norm(coth(t)^2 - 1 - csch(t)^2) - - norm(asin(sin(t)) - t) - norm(acos(cos(t)) - t) - norm(atan(tan(t)) - t) - norm(acsc(t) - asin(1/t)) - norm(asec(t) - acos(1/t)) - norm(acot(t) - acot(1/t)) - norm(asinh(sinh(t)) - t) - norm(acosh(cosh(t)) - t) - norm(atanh(tanh(t)) - t) - norm(acsch(t) - asinh(1/t)) - norm(asech(t) - acosh(1/t)) - norm(acoth(t) - acoth(1/t)) - norm(asinc(t) - asin(t)/t) - norm(asinhc(t) - asinh(t)/t) - - norm(erfc(t) - 1 + erf(t)) - norm(erf(-t) + erf(t)) - norm(angle(t) - atan(imag(t),real(t))) - norm(complex(t) - t) + t[0] = 0.5+0.5im; t[[1]] = 2+2im; t[[2]] = 3+3im; t[[3]] = 4+4im; t[[4]] = 5+5im; t[[5]] = 6+6im + norm(sin(t)^2+cos(t)^2 - 1) < tol + norm(1/sin(t) - csc(t)) < tol + norm(1/cos(t) - sec(t)) < tol + norm(1/tan(t) - cot(t)) < tol + norm(sin(t)/cos(t) - tan(t)) < tol + norm(cos(2*t) - cos(t)^2 + sin(t)^2) < tol + norm(sec(t)^2 - 1 - tan(t)^2) < tol + norm(sin(t/2) - sqrt((1-cos(t))/2)) < tol + norm(cos(t/2) - sqrt((1+cos(t))/2)) < tol + norm(sqrt(t^2) - t) < tol + norm(csc(t)^2 - cot(t)^2 - 1) < tol + norm(exp(log(t)) - t) < tol + norm(log(exp(t)) - t) < tol + norm(log(exp(t)) - exp(log(t))) < tol + norm(log(t^2) - 2*log(t)) < tol + norm(5*log(t) - log(t^5) - 2*pi*im) < tol + norm(t*log(5) - log(5^t)) < tol + norm(sinc(t/pi) - sin(t)/t) < tol + norm(sinhc(t/pi) - sinh(t)/t) < tol + norm(exp(im*t) - cos(t) - im*sin(t)) < tol + norm(sinh(t) - (exp(t) - exp(-t))/2) < tol + norm(cosh(t) - (exp(t) + exp(-t))/2) < tol + norm(tanh(t) - sinh(t)/cosh(t)) < tol + norm(csch(t) - 1/sinh(t)) < tol + norm(sech(t) - 1/cosh(t)) < tol + norm(coth(t) - cosh(t)/sinh(t)) < tol + norm(coth(t) - 1/tanh(t)) < tol + norm(cosh(t)^2 - sinh(t)^2 - 1) < tol + norm(1 - tanh(t)^2 - sech(t)^2) < tol + norm(coth(t)^2 - 1 - csch(t)^2) < tol + + norm(asin(sin(t)) - t) < tol + norm(acos(cos(t)) - t) < tol + norm(atan(tan(t)) - t) < tol + norm(acsc(t) - asin(1/t)) < tol + norm(asec(t) - acos(1/t)) < tol + norm(acot(t) - atan(1/t)) < tol + norm(asinh(sinh(t)) - t) < tol + norm(acosh(cosh(t)) - t) < tol + norm(atanh(tanh(t)) - t) < tol + norm(acsch(t) - asinh(1/t)) < tol + norm(asech(t) - acosh(1/t)) < tol + norm(acoth(t) - atanh(1/t)) < tol + norm(asinc(t/pi) - asin(t)/t) < tol + norm(asinhc(t/pi) - asinh(t)/t) < tol + + norm(erfc(t) - 1 + erf(t)) < tol + norm(erf(-t) + erf(t)) < tol + norm(angle(t) - atan(imag(t),real(t))) < tol + norm(complex(t) - t) < tol d = Descriptor(3,10,2,10) v = vars(d) @@ -503,216 +511,216 @@ function type_stable_test() tol = 1e-18 f = sin(v[1]) - abs(f[0] - 0) - abs(f[1] - 1) - abs(f[2] - 0) - abs(f[3] - -1/factorial(3)) - abs(f[4] - 0) - abs(f[5] - 1/factorial(5)) - abs(f[6] - 0) - abs(f[7] - -1/factorial(7)) - abs(f[8] - 0) - abs(f[9] - 1/factorial(9)) - abs(f[10] - 0) - - abs(f[1=>1] - f[1]) - abs(f[1=>2] - f[2]) - abs(f[1=>3] - f[3]) - abs(f[1=>4] - f[4]) - abs(f[1=>5] - f[5]) - abs(f[1=>6] - f[6]) - abs(f[1=>7] - f[7]) - abs(f[1=>8] - f[8]) - abs(f[1=>9] - f[9]) - abs(f[1=>10] - f[10]) + abs(f[[0]] - 0) < tol + abs(f[[1]] - 1) < tol + abs(f[[2]] - 0) < tol + abs(f[[3]] - -1/factorial(3)) < tol + abs(f[[4]] - 0) < tol + abs(f[[5]] - 1/factorial(5)) < tol + abs(f[[6]] - 0) < tol + abs(f[[7]] - -1/factorial(7)) < tol + abs(f[[8]] - 0) < tol + abs(f[[9]] - 1/factorial(9)) < tol + abs(f[[10]] - 0) < tol + + abs(f[[1=>1]] - f[[1]]) < tol + abs(f[[1=>2]] - f[[2]]) < tol + abs(f[[1=>3]] - f[[3]]) < tol + abs(f[[1=>4]] - f[[4]]) < tol + abs(f[[1=>5]] - f[[5]]) < tol + abs(f[[1=>6]] - f[[6]]) < tol + abs(f[[1=>7]] - f[[7]]) < tol + abs(f[[1=>8]] - f[[8]]) < tol + abs(f[[1=>9]] - f[[9]]) < tol + abs(f[[1=>10]] - f[[10]]) < tol fc = complex(f) - abs(fc[0] - 0) - abs(fc[1] - 1) - abs(fc[2] - 0) - abs(fc[3] - -1/factorial(3)) - abs(fc[4] - 0) - abs(fc[5] - 1/factorial(5)) - abs(fc[6] - 0) - abs(fc[7] - -1/factorial(7)) - abs(fc[8] - 0) - abs(fc[9] - 1/factorial(9)) - abs(fc[10] - 0) - - abs(fc[1=>1] - f[1]) - abs(fc[1=>2] - f[2]) - abs(fc[1=>3] - f[3]) - abs(fc[1=>4] - f[4]) - abs(fc[1=>5] - f[5]) - abs(fc[1=>6] - f[6]) - abs(fc[1=>7] - f[7]) - abs(fc[1=>8] - f[8]) - abs(fc[1=>9] - f[9]) - abs(fc[1=>10] - f[10]) + abs(fc[[0]] - 0) < tol + abs(fc[[1]] - 1) < tol + abs(fc[[2]] - 0) < tol + abs(fc[[3]] - -1/factorial(3)) < tol + abs(fc[[4]] - 0) < tol + abs(fc[[5]] - 1/factorial(5)) < tol + abs(fc[[6]] - 0) < tol + abs(fc[[7]] - -1/factorial(7)) < tol + abs(fc[[8]] - 0) < tol + abs(fc[[9]] - 1/factorial(9)) < tol + abs(fc[[10]] - 0) < tol + + abs(fc[[1=>1]] - f[[1]]) < tol + abs(fc[[1=>2]] - f[[2]]) < tol + abs(fc[[1=>3]] - f[[3]]) < tol + abs(fc[[1=>4]] - f[[4]]) < tol + abs(fc[[1=>5]] - f[[5]]) < tol + abs(fc[[1=>6]] - f[[6]]) < tol + abs(fc[[1=>7]] - f[[7]]) < tol + abs(fc[[1=>8]] - f[[8]]) < tol + abs(fc[[1=>9]] - f[[9]]) < tol + abs(fc[[1=>10]] - f[[10]]) < tol f2 = sin(v[1]) + cos(v[2]) - abs(f2[0] - 1) - abs(f2[1] - 1) - abs(f2[2] - 0) - abs(f2[3] - -1/factorial(3)) - abs(f2[4] - 0) - abs(f2[5] - 1/factorial(5)) - abs(f2[6] - 0) - abs(f2[7] - -1/factorial(7)) - abs(f2[8] - 0) - abs(f2[9] - 1/factorial(9)) - abs(f2[10] - 0) - - abs(f2[0,0] - 1) - abs(f2[0,1] - 0) - abs(f2[0,2] - -1/factorial(2)) - abs(f2[0,3] - 0) - abs(f2[0,4] - 1/factorial(4)) - abs(f2[0,5] - 0) - abs(f2[0,6] - -1/factorial(6)) - abs(f2[0,7] - 0) - abs(f2[0,8] - 1/factorial(8)) - abs(f2[0,9] - 0) - abs(f2[0,10] - -1/factorial(10)) - - abs(f2[1=>1] - f2[1]) - abs(f2[1=>2] - f2[2]) - abs(f2[1=>3] - f2[3]) - abs(f2[1=>4] - f2[4]) - abs(f2[1=>5] - f2[5]) - abs(f2[1=>6] - f2[6]) - abs(f2[1=>7] - f2[7]) - abs(f2[1=>8] - f2[8]) - abs(f2[1=>9] - f2[9]) - abs(f2[1=>10] - f2[10]) - - abs(f2[2=>1] - f2[0,1]) - abs(f2[2=>2] - f2[0,2]) - abs(f2[2=>3] - f2[0,3]) - abs(f2[2=>4] - f2[0,4]) - abs(f2[2=>5] - f2[0,5]) - abs(f2[2=>6] - f2[0,6]) - abs(f2[2=>7] - f2[0,7]) - abs(f2[2=>8] - f2[0,8]) - abs(f2[2=>9] - f2[0,9]) - abs(f2[2=>10] - f2[0,10]) + abs(f2[[0]] - 1) < tol + abs(f2[[1]] - 1) < tol + abs(f2[[2]] - 0) < tol + abs(f2[[3]] - -1/factorial(3)) < tol + abs(f2[[4]] - 0) < tol + abs(f2[[5]] - 1/factorial(5)) < tol + abs(f2[[6]] - 0) < tol + abs(f2[[7]] - -1/factorial(7)) < tol + abs(f2[[8]] - 0) < tol + abs(f2[[9]] - 1/factorial(9)) < tol + abs(f2[[10]] - 0) < tol + + abs(f2[[0,0]] - 1) < tol + abs(f2[[0,1]] - 0) < tol + abs(f2[[0,2]] - -1/factorial(2)) < tol + abs(f2[[0,3]] - 0) < tol + abs(f2[[0,4]] - 1/factorial(4)) < tol + abs(f2[[0,5]] - 0) < tol + abs(f2[[0,6]] - -1/factorial(6)) < tol + abs(f2[[0,7]] - 0) < tol + abs(f2[[0,8]] - 1/factorial(8)) < tol + abs(f2[[0,9]] - 0) < tol + abs(f2[[0,10]] - -1/factorial(10)) < tol + + abs(f2[[1=>1]] - f2[[1]]) < tol + abs(f2[[1=>2]] - f2[[2]]) < tol + abs(f2[[1=>3]] - f2[[3]]) < tol + abs(f2[[1=>4]] - f2[[4]]) < tol + abs(f2[[1=>5]] - f2[[5]]) < tol + abs(f2[[1=>6]] - f2[[6]]) < tol + abs(f2[[1=>7]] - f2[[7]]) < tol + abs(f2[[1=>8]] - f2[[8]]) < tol + abs(f2[[1=>9]] - f2[[9]]) < tol + abs(f2[[1=>10]] - f2[[10]]) < tol + + abs(f2[[2=>1]] - f2[[0,1]]) < tol + abs(f2[[2=>2]] - f2[[0,2]]) < tol + abs(f2[[2=>3]] - f2[[0,3]]) < tol + abs(f2[[2=>4]] - f2[[0,4]]) < tol + abs(f2[[2=>5]] - f2[[0,5]]) < tol + abs(f2[[2=>6]] - f2[[0,6]]) < tol + abs(f2[[2=>7]] - f2[[0,7]]) < tol + abs(f2[[2=>8]] - f2[[0,8]]) < tol + abs(f2[[2=>9]] - f2[[0,9]]) < tol + abs(f2[[2=>10]] - f2[[0,10]]) < tol f2c = complex(sin(v[1]) + cos(v[2])) - abs(f2c[0] - 1) - abs(f2c[1] - 1) - abs(f2c[2] - 0) - abs(f2c[3] - -1/factorial(3)) - abs(f2c[4] - 0) - abs(f2c[5] - 1/factorial(5)) - abs(f2c[6] - 0) - abs(f2c[7] - -1/factorial(7)) - abs(f2c[8] - 0) - abs(f2c[9] - 1/factorial(9)) - abs(f2c[10] - 0) - - abs(f2c[0,0] - 1) - abs(f2c[0,1] - 0) - abs(f2c[0,2] - -1/factorial(2)) - abs(f2c[0,3] - 0) - abs(f2c[0,4] - 1/factorial(4)) - abs(f2c[0,5] - 0) - abs(f2c[0,6] - -1/factorial(6)) - abs(f2c[0,7] - 0) - abs(f2c[0,8] - 1/factorial(8)) - abs(f2c[0,9] - 0) - abs(f2c[0,10] - -1/factorial(10)) - - abs(f2c[1=>1] - f2c[1]) - abs(f2c[1=>2] - f2c[2]) - abs(f2c[1=>3] - f2c[3]) - abs(f2c[1=>4] - f2c[4]) - abs(f2c[1=>5] - f2c[5]) - abs(f2c[1=>6] - f2c[6]) - abs(f2c[1=>7] - f2c[7]) - abs(f2c[1=>8] - f2c[8]) - abs(f2c[1=>9] - f2c[9]) - abs(f2c[1=>10] - f2c[10]) - - abs(f2c[2=>1] - f2c[0,1]) - abs(f2c[2=>2] - f2c[0,2]) - abs(f2c[2=>3] - f2c[0,3]) - abs(f2c[2=>4] - f2c[0,4]) - abs(f2c[2=>5] - f2c[0,5]) - abs(f2c[2=>6] - f2c[0,6]) - abs(f2c[2=>7] - f2c[0,7]) - abs(f2c[2=>8] - f2c[0,8]) - abs(f2c[2=>9] - f2c[0,9]) - abs(f2c[2=>10] - f2c[0,10]) + abs(f2c[[0]] - 1) < tol + abs(f2c[[1]] - 1) < tol + abs(f2c[[2]] - 0) < tol + abs(f2c[[3]] - -1/factorial(3)) < tol + abs(f2c[[4]] - 0) < tol + abs(f2c[[5]] - 1/factorial(5)) < tol + abs(f2c[[6]] - 0) < tol + abs(f2c[[7]] - -1/factorial(7)) < tol + abs(f2c[[8]] - 0) < tol + abs(f2c[[9]] - 1/factorial(9)) < tol + abs(f2c[[10]] - 0) < tol + + abs(f2c[[0,0]] - 1) < tol + abs(f2c[[0,1]] - 0) < tol + abs(f2c[[0,2]] - -1/factorial(2)) < tol + abs(f2c[[0,3]] - 0) < tol + abs(f2c[[0,4]] - 1/factorial(4)) < tol + abs(f2c[[0,5]] - 0) < tol + abs(f2c[[0,6]] - -1/factorial(6)) < tol + abs(f2c[[0,7]] - 0) < tol + abs(f2c[[0,8]] - 1/factorial(8)) < tol + abs(f2c[[0,9]] - 0) < tol + abs(f2c[[0,10]] - -1/factorial(10)) < tol + + abs(f2c[[1=>1]] - f2c[[1]]) < tol + abs(f2c[[1=>2]] - f2c[[2]]) < tol + abs(f2c[[1=>3]] - f2c[[3]]) < tol + abs(f2c[[1=>4]] - f2c[[4]]) < tol + abs(f2c[[1=>5]] - f2c[[5]]) < tol + abs(f2c[[1=>6]] - f2c[[6]]) < tol + abs(f2c[[1=>7]] - f2c[[7]]) < tol + abs(f2c[[1=>8]] - f2c[[8]]) < tol + abs(f2c[[1=>9]] - f2c[[9]]) < tol + abs(f2c[[1=>10]] - f2c[[10]]) < tol + + abs(f2c[[2=>1]] - f2c[[0,1]]) < tol + abs(f2c[[2=>2]] - f2c[[0,2]]) < tol + abs(f2c[[2=>3]] - f2c[[0,3]]) < tol + abs(f2c[[2=>4]] - f2c[[0,4]]) < tol + abs(f2c[[2=>5]] - f2c[[0,5]]) < tol + abs(f2c[[2=>6]] - f2c[[0,6]]) < tol + abs(f2c[[2=>7]] - f2c[[0,7]]) < tol + abs(f2c[[2=>8]] - f2c[[0,8]]) < tol + abs(f2c[[2=>9]] - f2c[[0,9]]) < tol + abs(f2c[[2=>10]] - f2c[[0,10]]) < tol f3 = sin(v[1]) + cos(v[2]) + exp(p[1]) - abs(f3[0] - 2) - abs(f3[1] - 1) - abs(f3[2] - 0) - abs(f3[3] - -1/factorial(3)) - abs(f3[4] - 0) - abs(f3[5] - 1/factorial(5)) - abs(f3[6] - 0) - abs(f3[7] - -1/factorial(7)) - abs(f3[8] - 0) - abs(f3[9] - 1/factorial(9)) - abs(f3[10] - 0) - - abs(f3[0,0] - 2) - abs(f3[0,1] - 0) - abs(f3[0,2] - -1/factorial(2)) - abs(f3[0,3] - 0) - abs(f3[0,4] - 1/factorial(4)) - abs(f3[0,5] - 0) - abs(f3[0,6] - -1/factorial(6)) - abs(f3[0,7] - 0) - abs(f3[0,8] - 1/factorial(8)) - abs(f3[0,9] - 0) - abs(f3[0,10] - -1/factorial(10)) - - abs(f3[0,0,0,0] - 2) - abs(f3[0,0,0,1] - 1/factorial(1)) - abs(f3[0,0,0,2] - 1/factorial(2)) - abs(f3[0,0,0,3] - 1/factorial(3)) - abs(f3[0,0,0,4] - 1/factorial(4)) - abs(f3[0,0,0,5] - 1/factorial(5)) - abs(f3[0,0,0,6] - 1/factorial(6)) - abs(f3[0,0,0,7] - 1/factorial(7)) - abs(f3[0,0,0,8] - 1/factorial(8)) - abs(f3[0,0,0,9] - 1/factorial(9)) - abs(f3[0,0,0,10] - 1/factorial(10)) - - abs(f3[1=>1] - f3[1]) - abs(f3[1=>2] - f3[2]) - abs(f3[1=>3] - f3[3]) - abs(f3[1=>4] - f3[4]) - abs(f3[1=>5] - f3[5]) - abs(f3[1=>6] - f3[6]) - abs(f3[1=>7] - f3[7]) - abs(f3[1=>8] - f3[8]) - abs(f3[1=>9] - f3[9]) - abs(f3[1=>10] - f3[10]) - - abs(f3[2=>1] - f3[0,1]) - abs(f3[2=>2] - f3[0,2]) - abs(f3[2=>3] - f3[0,3]) - abs(f3[2=>4] - f3[0,4]) - abs(f3[2=>5] - f3[0,5]) - abs(f3[2=>6] - f3[0,6]) - abs(f3[2=>7] - f3[0,7]) - abs(f3[2=>8] - f3[0,8]) - abs(f3[2=>9] - f3[0,9]) - abs(f3[2=>10] - f3[0,10]) - - abs(f3[params=[1=>1]] - f3[0,0,0,1]) - abs(f3[params=[1=>2]] - f3[0,0,0,2]) - abs(f3[params=[1=>3]] - f3[0,0,0,3]) - abs(f3[params=[1=>4]] - f3[0,0,0,4]) - abs(f3[params=[1=>5]] - f3[0,0,0,5]) - abs(f3[params=[1=>6]] - f3[0,0,0,6]) - abs(f3[params=[1=>7]] - f3[0,0,0,7]) - abs(f3[params=[1=>8]] - f3[0,0,0,8]) - abs(f3[params=[1=>9]] - f3[0,0,0,9]) - abs(f3[params=[1=>10]] - f3[0,0,0,10]) + abs(f3[[0]] - 2) < tol + abs(f3[[1]] - 1) < tol + abs(f3[[2]] - 0) < tol + abs(f3[[3]] - -1/factorial(3)) < tol + abs(f3[[4]] - 0) < tol + abs(f3[[5]] - 1/factorial(5)) < tol + abs(f3[[6]] - 0) < tol + abs(f3[[7]] - -1/factorial(7)) < tol + abs(f3[[8]] - 0) < tol + abs(f3[[9]] - 1/factorial(9)) < tol + abs(f3[[10]] - 0) < tol + + abs(f3[[0,0]] - 2) < tol + abs(f3[[0,1]] - 0) < tol + abs(f3[[0,2]] - -1/factorial(2)) < tol + abs(f3[[0,3]] - 0) < tol + abs(f3[[0,4]] - 1/factorial(4)) < tol + abs(f3[[0,5]] - 0) < tol + abs(f3[[0,6]] - -1/factorial(6)) < tol + abs(f3[[0,7]] - 0) < tol + abs(f3[[0,8]] - 1/factorial(8)) < tol + abs(f3[[0,9]] - 0) < tol + abs(f3[[0,10]] - -1/factorial(10)) < tol + + abs(f3[[0,0,0,0]] - 2) < tol + abs(f3[[0,0,0,1]] - 1/factorial(1)) < tol + abs(f3[[0,0,0,2]] - 1/factorial(2)) < tol + abs(f3[[0,0,0,3]] - 1/factorial(3)) < tol + abs(f3[[0,0,0,4]] - 1/factorial(4)) < tol + abs(f3[[0,0,0,5]] - 1/factorial(5)) < tol + abs(f3[[0,0,0,6]] - 1/factorial(6)) < tol + abs(f3[[0,0,0,7]] - 1/factorial(7)) < tol + abs(f3[[0,0,0,8]] - 1/factorial(8)) < tol + abs(f3[[0,0,0,9]] - 1/factorial(9)) < tol + abs(f3[[0,0,0,10]] - 1/factorial(10)) < tol + + abs(f3[[1=>1]] - f3[[1]]) < tol + abs(f3[[1=>2]] - f3[[2]]) < tol + abs(f3[[1=>3]] - f3[[3]]) < tol + abs(f3[[1=>4]] - f3[[4]]) < tol + abs(f3[[1=>5]] - f3[[5]]) < tol + abs(f3[[1=>6]] - f3[[6]]) < tol + abs(f3[[1=>7]] - f3[[7]]) < tol + abs(f3[[1=>8]] - f3[[8]]) < tol + abs(f3[[1=>9]] - f3[[9]]) < tol + abs(f3[[1=>10]] - f3[[10]]) < tol + + abs(f3[[2=>1]]- f3[[0,1]]) < tol + abs(f3[[2=>2]]- f3[[0,2]]) < tol + abs(f3[[2=>3]]- f3[[0,3]]) < tol + abs(f3[[2=>4]]- f3[[0,4]]) < tol + abs(f3[[2=>5]]- f3[[0,5]]) < tol + abs(f3[[2=>6]]- f3[[0,6]]) < tol + abs(f3[[2=>7]]- f3[[0,7]]) < tol + abs(f3[[2=>8]]- f3[[0,8]]) < tol + abs(f3[[2=>9]]- f3[[0,9]]) < tol + abs(f3[[2=>10]]- f3[[0,10]]) < tol + + abs(f3[params=[1=>1]] - f3[[0,0,0,1]]) < tol + abs(f3[params=[1=>2]] - f3[[0,0,0,2]]) < tol + abs(f3[params=[1=>3]] - f3[[0,0,0,3]]) < tol + abs(f3[params=[1=>4]] - f3[[0,0,0,4]]) < tol + abs(f3[params=[1=>5]] - f3[[0,0,0,5]]) < tol + abs(f3[params=[1=>6]] - f3[[0,0,0,6]]) < tol + abs(f3[params=[1=>7]] - f3[[0,0,0,7]]) < tol + abs(f3[params=[1=>8]] - f3[[0,0,0,8]]) < tol + abs(f3[params=[1=>9]] - f3[[0,0,0,9]]) < tol + abs(f3[params=[1=>10]] - f3[[0,0,0,10]]) < tol d = Descriptor(1, 5) t = TPS(use=d) @@ -738,81 +746,81 @@ function type_stable_test() tol = 1e-14 # TPS: - @FastGTPSA(norm(t1 + t2 - t3)) - @FastGTPSA(norm(t2 + t1 - t3)) - @FastGTPSA(norm(t1 + 2 - t3)) - @FastGTPSA(norm(2 + t1 - t3)) - @FastGTPSA(norm(t3 - t2 - t1)) - @FastGTPSA(norm(t2 - t3 - -t1)) - @FastGTPSA(norm(t3 - 2 - t1)) - @FastGTPSA(norm(2 - t3 - -t1)) - @FastGTPSA(norm(t2 * t3 - 6)) - @FastGTPSA(norm(t3 * t2 - 6)) - @FastGTPSA(norm(t2 * 5 - 10)) - @FastGTPSA(norm(5 * t2 - 10 * t1)) - @FastGTPSA(norm(t1 / t2 - 1/2)) - @FastGTPSA(norm(t2 / t1 - 2)) - @FastGTPSA(norm(1 / t2 - 1/2)) - @FastGTPSA(norm(t2 / 3 - 2/3)) - @FastGTPSA(norm(t2 / t2 - t1)) - @FastGTPSA(norm(t2 / t2 - 1)) - @FastGTPSA(norm(t2 ^ t3 - 8)) - @FastGTPSA(norm(t3 ^ t2 - 9)) - @FastGTPSA(norm(t2 ^ 3 - 8)) - @FastGTPSA(norm(t2 ^ (1/2) - sqrt(2))) - @FastGTPSA(norm(t2 ^ (1/2) - sqrt(t2))) - @FastGTPSA(norm(2 ^ t3 - 8)) - @FastGTPSA(norm(inv(t3) - 1/t3)) - @FastGTPSA(norm(inv(t3) - 1/3)) + @FastGTPSA(norm(t1 + t2 - t3)) < tol + @FastGTPSA(norm(t2 + t1 - t3)) < tol + @FastGTPSA(norm(t1 + 2 - t3)) < tol + @FastGTPSA(norm(2 + t1 - t3)) < tol + @FastGTPSA(norm(t3 - t2 - t1)) < tol + @FastGTPSA(norm(t2 - t3 - -t1)) < tol + @FastGTPSA(norm(t3 - 2 - t1)) < tol + @FastGTPSA(norm(2 - t3 - -t1)) < tol + @FastGTPSA(norm(t2 * t3 - 6)) < tol + @FastGTPSA(norm(t3 * t2 - 6)) < tol + @FastGTPSA(norm(t2 * 5 - 10)) < tol + @FastGTPSA(norm(5 * t2 - 10 * t1)) < tol + @FastGTPSA(norm(t1 / t2 - 1/2)) < tol + @FastGTPSA(norm(t2 / t1 - 2)) < tol + @FastGTPSA(norm(1 / t2 - 1/2)) < tol + @FastGTPSA(norm(t2 / 3 - 2/3)) < tol + @FastGTPSA(norm(t2 / t2 - t1)) < tol + @FastGTPSA(norm(t2 / t2 - 1)) < tol + @FastGTPSA(norm(t2 ^ t3 - 8)) < tol + @FastGTPSA(norm(t3 ^ t2 - 9)) < tol + @FastGTPSA(norm(t2 ^ 3 - 8)) < tol + @FastGTPSA(norm(t2 ^ (1/2) - sqrt(2))) < tol + @FastGTPSA(norm(t2 ^ (1/2) - sqrt(t2))) < tol + @FastGTPSA(norm(2 ^ t3 - 8)) < tol + @FastGTPSA(norm(inv(t3) - 1/t3)) < tol + @FastGTPSA(norm(inv(t3) - 1/3)) < tol # ComplexTPS: - @FastGTPSA(norm(ct1 + ct2 - ct3)) - @FastGTPSA(norm(ct2 + ct1 - ct3)) - @FastGTPSA(norm(ct1 + (2+2im) - ct3)) - @FastGTPSA(norm((2+2im) + ct1 - ct3)) - @FastGTPSA(norm(ct3 - ct2 - ct1)) - @FastGTPSA(norm(ct2 - ct3 - -ct1)) - @FastGTPSA(norm(ct3 - (2+2im) - ct1)) - @FastGTPSA(norm((2+2im) - ct3 - -ct1)) - @FastGTPSA(norm(ct2 * ct3 - (2+2im)*(3+3im))) - @FastGTPSA(norm(ct3 * ct2 - (2+2im)*(3+3im))) - @FastGTPSA(norm(ct2 * 5 - (10+10im))) - @FastGTPSA(norm(5 * ct2 - (10 * ct1))) - @FastGTPSA(norm(ct1 / ct2 - (1+im)/(2+2im))) - @FastGTPSA(norm(ct2 / ct1 - 2)) - @FastGTPSA(norm(1 / ct2 - 1/(2+2im))) - @FastGTPSA(norm(ct2 / 3 - (2+2im)/3)) - @FastGTPSA(norm(ct2 / ct2 - 1)) - @FastGTPSA(norm(ct2 ^ ct3 - (2+2im)^(3+3im))) - @FastGTPSA(norm(ct3 ^ ct2 - (3+3im)^(2+2im))) - @FastGTPSA(norm(ct2 ^ 3 - (2+2im)^3)) - @FastGTPSA(norm(ct2 ^ (1/2) - sqrt(2+2im))) - @FastGTPSA(norm(ct2 ^ (1/2) - sqrt(ct2))) - @FastGTPSA(norm(2 ^ ct3 - 2^(3+3im))) - @FastGTPSA(norm(inv(ct3) - 1/ct3)) - @FastGTPSA(norm(inv(ct3) - 1/(3+3im))) + @FastGTPSA(norm(ct1 + ct2 - ct3)) < tol + @FastGTPSA(norm(ct2 + ct1 - ct3)) < tol + @FastGTPSA(norm(ct1 + (2+2im) - ct3)) < tol + @FastGTPSA(norm((2+2im) + ct1 - ct3)) < tol + @FastGTPSA(norm(ct3 - ct2 - ct1)) < tol + @FastGTPSA(norm(ct2 - ct3 - -ct1)) < tol + @FastGTPSA(norm(ct3 - (2+2im) - ct1)) < tol + @FastGTPSA(norm((2+2im) - ct3 - -ct1)) < tol + @FastGTPSA(norm(ct2 * ct3 - (2+2im)*(3+3im))) < tol + @FastGTPSA(norm(ct3 * ct2 - (2+2im)*(3+3im))) < tol + @FastGTPSA(norm(ct2 * 5 - (10+10im))) < tol + @FastGTPSA(norm(5 * ct2 - (10 * ct1))) < tol + @FastGTPSA(norm(ct1 / ct2 - (1+im)/(2+2im))) < tol + @FastGTPSA(norm(ct2 / ct1 - 2)) < tol + @FastGTPSA(norm(1 / ct2 - 1/(2+2im))) < tol + @FastGTPSA(norm(ct2 / 3 - (2+2im)/3)) < tol + @FastGTPSA(norm(ct2 / ct2 - 1)) < tol + @FastGTPSA(norm(ct2 ^ ct3 - (2+2im)^(3+3im))) < tol + @FastGTPSA(norm(ct3 ^ ct2 - (3+3im)^(2+2im))) < tol + @FastGTPSA(norm(ct2 ^ 3 - (2+2im)^3)) < tol + @FastGTPSA(norm(ct2 ^ (1/2) - sqrt(2+2im))) < tol + @FastGTPSA(norm(ct2 ^ (1/2) - sqrt(ct2))) < tol + @FastGTPSA(norm(2 ^ ct3 - 2^(3+3im))) < tol + @FastGTPSA(norm(inv(ct3) - 1/ct3)) < tol + @FastGTPSA(norm(inv(ct3) - 1/(3+3im))) < tol # Promotion of TPS to ComplexTPS - @FastGTPSA(norm(t1 + ct2 - (1 + (2+2im)))) - @FastGTPSA(norm(ct2 + t1 - (1 + (2+2im)))) - @FastGTPSA(norm(t1 + (2+2im) - (1 + (2+2im)))) - @FastGTPSA(norm((2+2im) + t1 - (1 + (2+2im)))) - @FastGTPSA(norm(t3 - ct2 - (3 - (2+2im)))) - @FastGTPSA(norm(ct2 - t3 - ((2+2im) - 3))) - @FastGTPSA(norm(t3 - (2+2im) - (3 - (2+2im)))) - @FastGTPSA(norm((2+2im) - t3 - ((2+2im) - 3))) - @FastGTPSA(norm(t2 * ct3 - 2 * (3+3im))) - @FastGTPSA(norm(ct3 * t2 - 2 * (3+3im))) - @FastGTPSA(norm(t2 * (3+3im) - 2 * (3+3im))) - @FastGTPSA(norm((3+3im) * t2 - 2 * (3+3im))) - @FastGTPSA(norm(t2 / ct3 - 2/(3+3im))) - @FastGTPSA(norm(ct3 / t2 - (3+3im)/2)) - @FastGTPSA(norm(t2 / (3+3im) - 2/(3+3im))) - @FastGTPSA(norm((3+3im) / t2 - (3+3im)/2)) - @FastGTPSA(norm(t2 ^ ct3 - 2^(3+3im))) - @FastGTPSA(norm(ct3 ^ t2 - (3+3im)^2)) - @FastGTPSA(norm(t2 ^ (3+3im) - 2^(3+3im))) - @FastGTPSA(norm((3+3im)^t2 - (3+3im)^2)) + @FastGTPSA(norm(t1 + ct2 - (1 + (2+2im)))) < tol + @FastGTPSA(norm(ct2 + t1 - (1 + (2+2im)))) < tol + @FastGTPSA(norm(t1 + (2+2im) - (1 + (2+2im)))) < tol + @FastGTPSA(norm((2+2im) + t1 - (1 + (2+2im)))) < tol + @FastGTPSA(norm(t3 - ct2 - (3 - (2+2im)))) < tol + @FastGTPSA(norm(ct2 - t3 - ((2+2im) - 3))) < tol + @FastGTPSA(norm(t3 - (2+2im) - (3 - (2+2im)))) < tol + @FastGTPSA(norm((2+2im) - t3 - ((2+2im) - 3))) < tol + @FastGTPSA(norm(t2 * ct3 - 2 * (3+3im))) < tol + @FastGTPSA(norm(ct3 * t2 - 2 * (3+3im))) < tol + @FastGTPSA(norm(t2 * (3+3im) - 2 * (3+3im))) < tol + @FastGTPSA(norm((3+3im) * t2 - 2 * (3+3im))) < tol + @FastGTPSA(norm(t2 / ct3 - 2/(3+3im))) < tol + @FastGTPSA(norm(ct3 / t2 - (3+3im)/2)) < tol + @FastGTPSA(norm(t2 / (3+3im) - 2/(3+3im))) < tol + @FastGTPSA(norm((3+3im) / t2 - (3+3im)/2)) < tol + @FastGTPSA(norm(t2 ^ ct3 - 2^(3+3im))) < tol + @FastGTPSA(norm(ct3 ^ t2 - (3+3im)^2)) < tol + @FastGTPSA(norm(t2 ^ (3+3im) - 2^(3+3im))) < tol + @FastGTPSA(norm((3+3im)^t2 - (3+3im)^2)) < tol # Make sure stack is 0: desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) @@ -834,76 +842,78 @@ function type_stable_test() t3[0] = 3 - @FastGTPSA(norm(abs(-t) - abs(-v) )) - @FastGTPSA(norm(sqrt(t) - sqrt(v))) - @FastGTPSA(norm(exp(t) - exp(v))) - @FastGTPSA(norm(log(t) - log(v))) - @FastGTPSA(norm(sin(t) - sin(v))) - @FastGTPSA(norm(cos(t) - cos(v))) - @FastGTPSA(norm(tan(t) - tan(v))) - @FastGTPSA(norm(csc(t) - csc(v))) - @FastGTPSA(norm(sec(t) - sec(v))) - @FastGTPSA(norm(cot(t) - cot(v))) - @FastGTPSA(norm(sinc(t) - sinc(v))) - @FastGTPSA(norm(sinh(t) - sinh(v))) - @FastGTPSA(norm(cosh(t) - cosh(v))) - @FastGTPSA(norm(tanh(t) - tanh(v))) - @FastGTPSA(norm(csch(t) - csch(v))) - @FastGTPSA(norm(sech(t) - sech(v))) - @FastGTPSA(norm(coth(t) - coth(v))) - @FastGTPSA(norm(asin(t) - asin(v))) - @FastGTPSA(norm(acos(t) - acos(v))) - @FastGTPSA(norm(atan(t) - atan(v))) - @FastGTPSA(norm(acsc(1/t) - acsc(1/v))) - @FastGTPSA(norm(asec(1/t) - asec(1/v))) - @FastGTPSA(norm(acot(1/t) - acot(1/v))) - @FastGTPSA(norm(asinh(t) - asinh(v))) - @FastGTPSA(norm(acosh(1/t) - acosh(1/v))) - @FastGTPSA(norm(atanh(t) - atanh(v))) - @FastGTPSA(norm(acsch(1/t) - acsch(1/v))) - @FastGTPSA(norm(asech(t) - asech(v))) - @FastGTPSA(norm(acoth(1/t) - acoth(1/v))) - @FastGTPSA(norm(asinc(t/pi) - asin(v)/(v))) - @FastGTPSA(norm(asinhc(t/pi) - asinh(v)/(v))) - @FastGTPSA(norm(zero(t) - zero(v))) - @FastGTPSA(norm(real(t) - real(v))) - @FastGTPSA(norm(imag(t) - imag(v))) - @FastGTPSA(norm(conj(t) - conj(v))) - @FastGTPSA(norm(sinhc(t/pi) - sinh(v)/v)) - @FastGTPSA(norm(erf(t) - erf(v))) - @FastGTPSA(norm(erfc(t) - erfc(v))) - @FastGTPSA(norm(-im*erf(t*im) - erfi(v))) - @FastGTPSA(norm(atan(t3,t2) - atan(3,2))) - @FastGTPSA(norm(atan(t3,2) - atan(3,2))) - @FastGTPSA(norm(atan(3,t2) - atan(3,2))) - @FastGTPSA(norm(atan(t3,-t2) - atan(3,-2))) - @FastGTPSA(norm(atan(t3,-2) - atan(3,-2))) - @FastGTPSA(norm(atan(3,-t2) - atan(3,-2))) - @FastGTPSA(norm(atan(-t3,-t2) - atan(-3,-2))) - @FastGTPSA(norm(atan(-t3,-2) - atan(-3,-2))) - @FastGTPSA(norm(atan(-3,-t2) - atan(-3,-2))) - @FastGTPSA(norm(atan(-t3,t2) - atan(-3,2))) - @FastGTPSA(norm(atan(-t3,2) - atan(-3,2))) - @FastGTPSA(norm(atan(-3,t2) - atan(-3,2))) - @FastGTPSA(norm(hypot(t2,t3) - hypot(2,3))) - @FastGTPSA(norm(hypot(2,t3) - hypot(2,3))) - @FastGTPSA(norm(hypot(t2,3) - hypot(2,3))) - @FastGTPSA(norm(hypot(t1,t2,t3) - hypot(1,2,3))) - @FastGTPSA(norm(hypot(1, t2, t3) - hypot(1,2,3))) - @FastGTPSA(norm(hypot(t1, 2, t3) - hypot(1,2,3))) - @FastGTPSA(norm(hypot(t1, t2, 3) - hypot(1,2,3))) - @FastGTPSA(norm(hypot(1, 2, t3) - hypot(1,2,3))) - @FastGTPSA(norm(hypot(1, t2, 3) - hypot(1,2,3))) - @FastGTPSA(norm(hypot(t1, 2, 3) - hypot(1,2,3))) - - @FastGTPSA(norm(angle(t2) - angle(2))) - @FastGTPSA(norm(angle(-t2) - angle(-2))) - @FastGTPSA(norm(complex(t3) - complex(3))) - @FastGTPSA(norm(complex(t2,t3) - complex(2,3))) - @FastGTPSA(norm(polar(t2) - (abs(2)+im*atan(0,2)))) - @FastGTPSA(norm(polar(-t1) - (abs(-1)+im*atan(0,-1)))) - @FastGTPSA(norm(rect(t2) - (2*cos(0) + 2*sin(0)))) - @FastGTPSA(norm(rect(-t1) - (-1*cos(0) + -1*sin(0)))) + @FastGTPSA(norm(abs(-t) - abs(-v) )) < tol + @FastGTPSA(norm(sqrt(t) - sqrt(v))) < tol + @FastGTPSA(norm(exp(t) - exp(v))) < tol + @FastGTPSA(norm(log(t) - log(v))) < tol + @FastGTPSA(norm(sin(t) - sin(v))) < tol + @FastGTPSA(norm(cos(t) - cos(v))) < tol + @FastGTPSA(norm(tan(t) - tan(v))) < tol + @FastGTPSA(norm(csc(t) - csc(v))) < tol + @FastGTPSA(norm(sec(t) - sec(v))) < tol + @FastGTPSA(norm(cot(t) - cot(v))) < tol + @FastGTPSA(norm(sinc(t) - sinc(v))) < tol + @FastGTPSA(norm(sinh(t) - sinh(v))) < tol + @FastGTPSA(norm(cosh(t) - cosh(v))) < tol + @FastGTPSA(norm(tanh(t) - tanh(v))) < tol + @FastGTPSA(norm(csch(t) - csch(v))) < tol + @FastGTPSA(norm(sech(t) - sech(v))) < tol + @FastGTPSA(norm(coth(t) - coth(v))) < tol + @FastGTPSA(norm(asin(t) - asin(v))) < tol + @FastGTPSA(norm(acos(t) - acos(v))) < tol + @FastGTPSA(norm(atan(t) - atan(v))) < tol + @FastGTPSA(norm(acsc(1/t) - acsc(1/v))) < tol + @FastGTPSA(norm(asec(1/t) - asec(1/v))) < tol + @FastGTPSA(norm(acot(1/t) - acot(1/v))) < tol + @FastGTPSA(norm(asinh(t) - asinh(v))) < tol + @FastGTPSA(norm(acosh(1/t) - acosh(1/v))) < tol + @FastGTPSA(norm(atanh(t) - atanh(v))) < tol + @FastGTPSA(norm(acsch(1/t) - acsch(1/v))) < tol + @FastGTPSA(norm(asech(t) - asech(v))) < tol + @FastGTPSA(norm(acoth(1/t) - acoth(1/v))) < tol + @FastGTPSA(norm(asinc(t/pi) - asin(v)/(v))) < tol + @FastGTPSA(norm(asinhc(t/pi) - asinh(v)/(v))) < tol + @FastGTPSA(norm(zero(t) - zero(v))) < tol + @FastGTPSA(norm(real(t) - real(v))) < tol + @FastGTPSA(norm(imag(t) - imag(v))) < tol + @FastGTPSA(norm(conj(t) - conj(v))) < tol + @FastGTPSA(norm(sinhc(t/pi) - sinh(v)/v)) < tol + @FastGTPSA(norm(erf(t) - erf(v))) < tol + @FastGTPSA(norm(erfc(t) - erfc(v))) < tol + @FastGTPSA(norm(-im*erf(t*im) - erfi(v))) < tol + @FastGTPSA(norm(atan(t3,t2) - atan(3,2))) < tol + @FastGTPSA(norm(atan(t3,2) - atan(3,2))) < tol + @FastGTPSA(norm(atan(3,t2) - atan(3,2))) < tol + @FastGTPSA(norm(atan(t3,-t2) - atan(3,-2))) < tol + @FastGTPSA(norm(atan(t3,-2) - atan(3,-2))) < tol + @FastGTPSA(norm(atan(3,-t2) - atan(3,-2))) < tol + @FastGTPSA(norm(atan(-t3,-t2) - atan(-3,-2))) < tol + @FastGTPSA(norm(atan(-t3,-2) - atan(-3,-2))) < tol + @FastGTPSA(norm(atan(-3,-t2) - atan(-3,-2))) < tol + @FastGTPSA(norm(atan(-t3,t2) - atan(-3,2))) < tol + @FastGTPSA(norm(atan(-t3,2) - atan(-3,2))) < tol + @FastGTPSA(norm(atan(-3,t2) - atan(-3,2))) < tol + + @FastGTPSA(norm(hypot(t2,t3) - hypot(2,3))) < tol + @FastGTPSA(norm(hypot(2,t3) - hypot(2,3))) < tol + @FastGTPSA(norm(hypot(t2,3) - hypot(2,3))) < tol + @FastGTPSA(norm(hypot(t1,t2,t3) - hypot(1,2,3))) < tol + @FastGTPSA(norm(hypot(1, t2, t3) - hypot(1,2,3))) < tol + @FastGTPSA(norm(hypot(t1, 2, t3) - hypot(1,2,3))) < tol + @FastGTPSA(norm(hypot(t1, t2, 3) - hypot(1,2,3))) < tol + @FastGTPSA(norm(hypot(1, 2, t3) - hypot(1,2,3))) < tol + @FastGTPSA(norm(hypot(1, t2, 3) - hypot(1,2,3))) < tol + @FastGTPSA(norm(hypot(t1, 2, 3) - hypot(1,2,3))) < tol + + @FastGTPSA(norm(angle(t2) - angle(2))) < tol + @FastGTPSA(norm(angle(-t2) - angle(-2))) < tol + @FastGTPSA(norm(complex(t3) - complex(3))) < tol + @FastGTPSA(norm(complex(t2,t3) - complex(2,3))) < tol + @FastGTPSA(norm(polar(t2) - (abs(2)+im*atan(0,2)))) < tol + @FastGTPSA(norm(polar(-t1) - (abs(-1)+im*atan(0,-1)))) < tol + @FastGTPSA(norm(rect(t2) - (2*cos(0) + im*2*sin(0)))) < tol + @FastGTPSA(norm(rect(-t1) - (-1*cos(0) + im*-1*sin(0)))) < tol + v = 0.5+0.5im t = ComplexTPS(t) @@ -914,86 +924,89 @@ function type_stable_test() ct2[0] = 2 + 2im ct3 = zero(ct1) ct3[0] = 3 + 3im - @FastGTPSA(norm(abs(-t) - abs(-v) )) - @FastGTPSA(norm(sqrt(t) - sqrt(v))) - @FastGTPSA(norm(exp(t) - exp(v))) - @FastGTPSA(norm(log(t) - log(v))) - @FastGTPSA(norm(sin(t) - sin(v))) - @FastGTPSA(norm(cos(t) - cos(v))) - @FastGTPSA(norm(tan(t) - tan(v))) - @FastGTPSA(norm(csc(t) - csc(v))) - @FastGTPSA(norm(sec(t) - sec(v))) - @FastGTPSA(norm(cot(t) - cot(v))) - @FastGTPSA(norm(sinc(t) - sinc(v))) - @FastGTPSA(norm(sinh(t) - sinh(v))) - @FastGTPSA(norm(cosh(t) - cosh(v))) - @FastGTPSA(norm(tanh(t) - tanh(v))) - @FastGTPSA(norm(csch(t) - csch(v))) - @FastGTPSA(norm(sech(t) - sech(v))) - @FastGTPSA(norm(coth(t) - coth(v))) - @FastGTPSA(norm(asin(t) - asin(v))) - @FastGTPSA(norm(acos(t) - acos(v))) - @FastGTPSA(norm(atan(t) - atan(v))) - @FastGTPSA(norm(acsc(t) - acsc(v))) - @FastGTPSA(norm(asec(t) - asec(v))) - @FastGTPSA(norm(acot(t) - acot(v))) - @FastGTPSA(norm(asinh(t) - asinh(v))) - @FastGTPSA(norm(acosh(t) - acosh(v))) - @FastGTPSA(norm(atanh(t) - atanh(v))) - @FastGTPSA(norm(acsch(t) - acsch(v))) - @FastGTPSA(norm(asech(t) - asech(v))) - @FastGTPSA(norm(acoth(t) - acoth(v))) - @FastGTPSA(norm(asinc(t) - asin(v)/v)) - @FastGTPSA(norm(asinhc(t) - asinh(v)/v)) - @FastGTPSA(norm(zero(t) - zero(v))) - @FastGTPSA(norm(real(t) - real(v))) - @FastGTPSA(norm(imag(t) - imag(v))) - @FastGTPSA(norm(conj(t) - conj(v))) - @FastGTPSA(norm(sinhc(t/pi) - sinh(v)/v)) - @FastGTPSA(norm(erf(t) - erf(v))) - @FastGTPSA(norm(erfc(t) - erfc(v))) - @FastGTPSA(norm(-im*erf(t*im) - erfi(v))) - @FastGTPSA(norm(hypot(ct2,ct3) - hypot(2+2im,3+3im))) - @FastGTPSA(norm(hypot(2+2im,ct3) - hypot(2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct2,3+3im) - hypot(2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct1,ct2,ct3) - hypot(1+1im,2+2im,3+3im))) - @FastGTPSA(norm(hypot(1+1im, ct2, ct3) - hypot(1+1im,2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct1, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct1, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im))) - @FastGTPSA(norm(hypot(1+1im, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im))) - @FastGTPSA(norm(hypot(1+1im, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct1, 2+2im, 3+3im) - hypot(1+1im,2+2im,3+3im))) - - @FastGTPSA(norm(angle(t2+im*t3) - angle(2+3im))) - @FastGTPSA(norm(angle(t2-im*t3) - angle(2-3im))) - @FastGTPSA(norm(angle(-t2-im*t3) - angle(-2-3im))) - @FastGTPSA(norm(angle(-t2+im*t3) - angle(-2+3im))) - @FastGTPSA(norm(angle(ct2) - angle(2+2im))) - @FastGTPSA(norm(angle(-ct2) - angle(-2-2im))) - @FastGTPSA(norm(complex(ct3) - complex(3+3im))) - @FastGTPSA(norm(polar(ct2) - (abs(2+2im)+im*angle(2+2im)))) - @FastGTPSA(norm(polar(-ct1) - (abs(-1-im)+im*angle(-1-im)))) - @FastGTPSA(norm(rect(ct2) - (2*cos(2) + 2*sin(2)))) - @FastGTPSA(norm(rect(-ct1) - (-1*cos(-1) + -1*sin(-1)))) + @FastGTPSA(norm(abs(-t) - abs(-v) )) < tol + @FastGTPSA(norm(sqrt(t) - sqrt(v))) < tol + @FastGTPSA(norm(exp(t) - exp(v))) < tol + @FastGTPSA(norm(log(t) - log(v))) < tol + @FastGTPSA(norm(sin(t) - sin(v))) < tol + @FastGTPSA(norm(cos(t) - cos(v))) < tol + @FastGTPSA(norm(tan(t) - tan(v))) < tol + @FastGTPSA(norm(csc(t) - csc(v))) < tol + @FastGTPSA(norm(sec(t) - sec(v))) < tol + @FastGTPSA(norm(cot(t) - cot(v))) < tol + @FastGTPSA(norm(sinc(t) - sinc(v))) < tol + @FastGTPSA(norm(sinh(t) - sinh(v))) < tol + @FastGTPSA(norm(cosh(t) - cosh(v))) < tol + @FastGTPSA(norm(tanh(t) - tanh(v))) < tol + @FastGTPSA(norm(csch(t) - csch(v))) < tol + @FastGTPSA(norm(sech(t) - sech(v))) < tol + @FastGTPSA(norm(coth(t) - coth(v))) < tol + + @FastGTPSA(norm(asin(t) - asin(v))) < tol + @FastGTPSA(norm(acos(t) - acos(v))) < tol + @FastGTPSA(norm(atan(t) - atan(v))) < tol + @FastGTPSA(norm(acsc(t) - acsc(v))) < tol + @FastGTPSA(norm(asec(t) - asec(v))) < tol + @FastGTPSA(norm(acot(t) - acot(v))) < tol + @FastGTPSA(norm(asinh(t) - asinh(v))) < tol + @FastGTPSA(norm(acosh(t) - acosh(v))) < tol + @FastGTPSA(norm(atanh(t) - atanh(v))) < tol + @FastGTPSA(norm(acsch(t) - acsch(v))) < tol + @FastGTPSA(norm(asech(t) - asech(v))) < tol + @FastGTPSA(norm(acoth(t) - acoth(v))) < tol + @FastGTPSA(norm(asinc(t/pi) - asin(v)/v)) < tol + @FastGTPSA(norm(asinhc(t/pi) - asinh(v)/v)) < tol + + @FastGTPSA(norm(zero(t) - zero(v))) < tol + @FastGTPSA(norm(real(t) - real(v))) < tol + @FastGTPSA(norm(imag(t) - imag(v))) < tol + @FastGTPSA(norm(conj(t) - conj(v))) < tol + @FastGTPSA(norm(sinhc(t/pi) - sinh(v)/v)) < tol + @FastGTPSA(norm(erf(t) - erf(v))) < tol + @FastGTPSA(norm(erfc(t) - erfc(v))) < tol + @FastGTPSA(norm(-im*erf(t*im) - erfi(v))) < tol + @FastGTPSA(norm(hypot(ct2,ct3) - hypot(2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(2+2im,ct3) - hypot(2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct2,3+3im) - hypot(2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1,ct2,ct3) - hypot(1+1im,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(1+1im, ct2, ct3) - hypot(1+1im,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(1+1im, 2+2im, ct3) - hypot(1+1im,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(1+1im, ct2, 3+3im) - hypot(1+1im,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1, 2+2im, 3+3im) - hypot(1+1im,2+2im,3+3im))) < tol + + @FastGTPSA(norm(angle(t2+im*t3) - angle(2+3im))) < tol + @FastGTPSA(norm(angle(t2-im*t3) - angle(2-3im))) < tol + @FastGTPSA(norm(angle(-t2-im*t3) - angle(-2-3im))) < tol + @FastGTPSA(norm(angle(-t2+im*t3) - angle(-2+3im))) < tol + @FastGTPSA(norm(angle(ct2) - angle(2+2im))) < tol + @FastGTPSA(norm(angle(-ct2) - angle(-2-2im))) < tol + @FastGTPSA(norm(complex(ct3) - complex(3+3im))) < tol + @FastGTPSA(norm(polar(ct2) - (abs(2+2im)+im*angle(2+2im)))) < tol + @FastGTPSA(norm(polar(-ct1) - (abs(-1-im)+im*angle(-1-im)))) < tol + @FastGTPSA(norm(rect(ct2) - (2*cos(2) + im*2*sin(2)))) < tol + @FastGTPSA(norm(rect(-ct1) - (-1*cos(-1) + im*-1*sin(-1)))) < tol + # Hypot, mixing TPS with ComplexTPS - @FastGTPSA(norm(hypot(ct1, ct2, t3) - hypot(1+1im,2+2im,3))) - @FastGTPSA(norm(hypot(ct1, t2, ct3) - hypot(1+1im,2,3+3im))) - @FastGTPSA(norm(hypot(t1, ct2, ct3) - hypot(1,2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct1, t2, t3) - hypot(1+1im,2,3))) - @FastGTPSA(norm(hypot(t1, ct2, t3) - hypot(1,2+2im,3))) - @FastGTPSA(norm(hypot(t1, t2, ct3) - hypot(1,2,3+3im))) - @FastGTPSA(norm(hypot(ct1,t2,3+3im) - hypot(1+1im,2,3+3im))) - @FastGTPSA(norm(hypot(t1, ct2, 3+3im) - hypot(1,2+2im,3+3im))) - @FastGTPSA(norm(hypot(ct1,2+2im,t3) - hypot(1+1im,2+2im,3))) - @FastGTPSA(norm(hypot(t1,2+2im,ct3) - hypot(1,2+2im,3+3im))) - @FastGTPSA(norm(hypot(1+1im,ct2,t3) - hypot(1+1im,2+2im,3))) - @FastGTPSA(norm(hypot(1+1im, t2, ct3) - hypot(1+1im,2,3+3im))) - @FastGTPSA(norm(hypot(t1,t2,3+3im) - hypot(1,2,3+3im))) - @FastGTPSA(norm(hypot(t1,2+2im,t3) - hypot(1,2+2im,3))) - @FastGTPSA(norm(hypot(1+1im,t2,t3) - hypot(1+1im,2,3))) - @FastGTPSA(norm(hypot(t1,2,3+3im) - hypot(1,2,3+3im))) - @FastGTPSA(norm(hypot(1,t2,3+3im) - hypot(1,2,3+3im))) - @FastGTPSA(norm(hypot(1+1im,2,t3) - hypot(1+1im,2,3))) + @FastGTPSA(norm(hypot(ct1, ct2, t3) - hypot(1+1im,2+2im,3))) < tol + @FastGTPSA(norm(hypot(ct1, t2, ct3) - hypot(1+1im,2,3+3im))) < tol + @FastGTPSA(norm(hypot(t1, ct2, ct3) - hypot(1,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1, t2, t3) - hypot(1+1im,2,3))) < tol + @FastGTPSA(norm(hypot(t1, ct2, t3) - hypot(1,2+2im,3))) < tol + @FastGTPSA(norm(hypot(t1, t2, ct3) - hypot(1,2,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1,t2,3+3im) - hypot(1+1im,2,3+3im))) < tol + @FastGTPSA(norm(hypot(t1, ct2, 3+3im) - hypot(1,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(ct1,2+2im,t3) - hypot(1+1im,2+2im,3))) < tol + @FastGTPSA(norm(hypot(t1,2+2im,ct3) - hypot(1,2+2im,3+3im))) < tol + @FastGTPSA(norm(hypot(1+1im,ct2,t3) - hypot(1+1im,2+2im,3))) < tol + @FastGTPSA(norm(hypot(1+1im, t2, ct3) - hypot(1+1im,2,3+3im))) < tol + @FastGTPSA(norm(hypot(t1,t2,3+3im) - hypot(1,2,3+3im))) < tol + @FastGTPSA(norm(hypot(t1,2+2im,t3) - hypot(1,2+2im,3))) < tol + @FastGTPSA(norm(hypot(1+1im,t2,t3) - hypot(1+1im,2,3))) < tol + @FastGTPSA(norm(hypot(t1,2,3+3im) - hypot(1,2,3+3im))) < tol + @FastGTPSA(norm(hypot(1,t2,3+3im) - hypot(1,2,3+3im))) < tol + @FastGTPSA(norm(hypot(1+1im,2,t3) - hypot(1+1im,2,3))) < tol # Make sure stack is 0: desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t1.tpsa).d)) @@ -1001,115 +1014,117 @@ function type_stable_test() ctmpidx = unsafe_load(desc.cti) ctmpidx == 0 tmpidx == 0 + d = Descriptor(1, 5) t = TPS(use=d) - t[0] = 0.5; t[1] = 2; t[2] = 3; t[3] = 4; t[4] = 5; t[5] = 6 + t[0] = 0.5; t[[1]] = 2; t[[2]] = 3; t[[3]] = 4; t[[4]] = 5; t[[5]] = 6 tol = 1e-10 - @FastGTPSA(norm(sin(t)^2+cos(t)^2 - 1)) - @FastGTPSA(norm(1/sin(t) - csc(t))) - @FastGTPSA(norm(1/cos(t) - sec(t))) - @FastGTPSA(norm(1/tan(t) - cot(t))) - @FastGTPSA(norm(sin(t)/cos(t) - tan(t))) - @FastGTPSA(norm(cos(2*t) - cos(t)^2 + sin(t)^2)) - @FastGTPSA(norm(sec(t)^2 - 1 - tan(t)^2)) - @FastGTPSA(norm(sin(t/2) - sqrt((1-cos(t))/2))) - @FastGTPSA(norm(cos(t/2) - sqrt((1+cos(t))/2))) - @FastGTPSA(norm(sqrt(t^2) - abs(t))) - @FastGTPSA(norm(csc(t)^2 - cot(t)^2 - 1)) - @FastGTPSA(norm(exp(log(t)) - t)) - @FastGTPSA(norm(log(exp(t)) - t)) - @FastGTPSA(norm(log(exp(t)) - exp(log(t)))) - @FastGTPSA(norm(log(t^2) - 2*log(t))) - @FastGTPSA(norm(5*log(t) - log(t^5))) - @FastGTPSA(norm(t*log(5) - log(5^t))) - @FastGTPSA(norm(sinc(t) - sin(pi*t)/(pi*t))) - @FastGTPSA(norm(sinhc(t/pi) - sinh(t)/t)) - @FastGTPSA(norm(exp(im*t) - cos(t) - im*sin(t))) - @FastGTPSA(norm(real(exp(im*t)) - cos(t))) - @FastGTPSA(norm(imag(exp(im*t)) - sin(t))) - @FastGTPSA(norm(sinh(t) - (exp(t) - exp(-t))/2)) - @FastGTPSA(norm(cosh(t) - (exp(t) + exp(-t))/2)) - @FastGTPSA(norm(tanh(t) - sinh(t)/cosh(t))) - @FastGTPSA(norm(csch(t) - 1/sinh(t))) - @FastGTPSA(norm(sech(t) - 1/cosh(t))) - @FastGTPSA(norm(coth(t) - cosh(t)/sinh(t))) - @FastGTPSA(norm(coth(t) - 1/tanh(t))) - @FastGTPSA(norm(cosh(t)^2 - sinh(t)^2 - 1)) - @FastGTPSA(norm(1 - tanh(t)^2 - sech(t)^2)) - @FastGTPSA(norm(coth(t)^2 - 1 - csch(t)^2)) - @FastGTPSA(norm(asin(sin(t)) - t)) - @FastGTPSA(norm(acos(cos(t)) - t)) - @FastGTPSA(norm(atan(tan(t)) - t)) - @FastGTPSA(norm(acsc(1/t) - asin(t))) - @FastGTPSA(norm(asec(1/t) - acos(t))) - @FastGTPSA(norm(acot(1/t) - atan(t))) - @FastGTPSA(norm(asinh(sinh(t)) - t)) - @FastGTPSA(norm(acosh(cosh(t)) - t)) - @FastGTPSA(norm(atanh(tanh(t)) - t)) - @FastGTPSA(norm(acsch(t) - asinh(1/t))) - @FastGTPSA(norm(asech(t) - acosh(1/t))) - @FastGTPSA(norm(acoth(1/t) - atanh(t))) - @FastGTPSA(norm(asinc(t/pi) - asin(t)/t)) - @FastGTPSA(norm(asinhc(t/pi) - asinh(t)/t)) - @FastGTPSA(norm(erfc(t) - 1 + erf(t))) - @FastGTPSA(norm(erf(-t) + erf(t))) - @FastGTPSA(norm(angle(t))) - @FastGTPSA(norm(complex(t) - t)) - @FastGTPSA(norm(complex(t,t) - (t+im*t))) + @FastGTPSA(norm(sin(t)^2+cos(t)^2 - 1)) < tol + @FastGTPSA(norm(1/sin(t) - csc(t))) < tol + @FastGTPSA(norm(1/cos(t) - sec(t))) < tol + @FastGTPSA(norm(1/tan(t) - cot(t))) < tol + @FastGTPSA(norm(sin(t)/cos(t) - tan(t))) < tol + @FastGTPSA(norm(cos(2*t) - cos(t)^2 + sin(t)^2)) < tol + @FastGTPSA(norm(sec(t)^2 - 1 - tan(t)^2)) < tol + @FastGTPSA(norm(sin(t/2) - sqrt((1-cos(t))/2))) < tol + @FastGTPSA(norm(cos(t/2) - sqrt((1+cos(t))/2))) < tol + @FastGTPSA(norm(sqrt(t^2) - abs(t))) < tol + @FastGTPSA(norm(csc(t)^2 - cot(t)^2 - 1)) < tol + @FastGTPSA(norm(exp(log(t)) - t)) < tol + @FastGTPSA(norm(log(exp(t)) - t)) < tol + @FastGTPSA(norm(log(exp(t)) - exp(log(t)))) < tol + @FastGTPSA(norm(log(t^2) - 2*log(t))) < tol + @FastGTPSA(norm(5*log(t) - log(t^5))) < tol + @FastGTPSA(norm(t*log(5) - log(5^t))) < tol + @FastGTPSA(norm(sinc(t) - sin(pi*t)/(pi*t))) < tol + @FastGTPSA(norm(sinhc(t/pi) - sinh(t)/t)) < tol + @FastGTPSA(norm(exp(im*t) - cos(t) - im*sin(t))) < tol + @FastGTPSA(norm(real(exp(im*t)) - cos(t))) < tol + @FastGTPSA(norm(imag(exp(im*t)) - sin(t))) < tol + @FastGTPSA(norm(sinh(t) - (exp(t) - exp(-t))/2)) < tol + @FastGTPSA(norm(cosh(t) - (exp(t) + exp(-t))/2)) < tol + @FastGTPSA(norm(tanh(t) - sinh(t)/cosh(t))) < tol + @FastGTPSA(norm(csch(t) - 1/sinh(t))) < tol + @FastGTPSA(norm(sech(t) - 1/cosh(t))) < tol + @FastGTPSA(norm(coth(t) - cosh(t)/sinh(t))) < tol + @FastGTPSA(norm(coth(t) - 1/tanh(t))) < tol + @FastGTPSA(norm(cosh(t)^2 - sinh(t)^2 - 1)) < tol + @FastGTPSA(norm(1 - tanh(t)^2 - sech(t)^2)) < tol + @FastGTPSA(norm(coth(t)^2 - 1 - csch(t)^2)) < tol + @FastGTPSA(norm(asin(sin(t)) - t)) < tol + @FastGTPSA(norm(acos(cos(t)) - t)) < tol + @FastGTPSA(norm(atan(tan(t)) - t)) < tol + @FastGTPSA(norm(acsc(1/t) - asin(t))) < tol + @FastGTPSA(norm(asec(1/t) - acos(t))) < tol + @FastGTPSA(norm(acot(1/t) - atan(t))) < tol + @FastGTPSA(norm(asinh(sinh(t)) - t)) < tol + @FastGTPSA(norm(acosh(cosh(t)) - t)) < tol + @FastGTPSA(norm(atanh(tanh(t)) - t)) < tol + @FastGTPSA(norm(acsch(t) - asinh(1/t))) < tol + @FastGTPSA(norm(asech(t) - acosh(1/t))) < tol + @FastGTPSA(norm(acoth(1/t) - atanh(t))) < tol + @FastGTPSA(norm(asinc(t/pi) - asin(t)/t)) < tol + @FastGTPSA(norm(asinhc(t/pi) - asinh(t)/t)) < tol + @FastGTPSA(norm(erfc(t) - 1 + erf(t))) < tol + @FastGTPSA(norm(erf(-t) + erf(t))) < tol + @FastGTPSA(norm(angle(t))) < tol + @FastGTPSA(norm(complex(t) - t)) < tol + @FastGTPSA(norm(complex(t,t) - (t+im*t))) < tol t = ComplexTPS(t) - t[0] = 0.5+0.5im; t[1] = 2+2im; t[2] = 3+3im; t[3] = 4+4im; t[4] = 5+5im; t[5] = 6+6im - @FastGTPSA(norm(sin(t)^2+cos(t)^2 - 1)) - @FastGTPSA(norm(1/sin(t) - csc(t))) - @FastGTPSA(norm(1/cos(t) - sec(t))) - @FastGTPSA(norm(1/tan(t) - cot(t))) - @FastGTPSA(norm(sin(t)/cos(t) - tan(t))) - @FastGTPSA(norm(cos(2*t) - cos(t)^2 + sin(t)^2)) - @FastGTPSA(norm(sec(t)^2 - 1 - tan(t)^2)) - @FastGTPSA(norm(sin(t/2) - sqrt((1-cos(t))/2))) - @FastGTPSA(norm(cos(t/2) - sqrt((1+cos(t))/2))) - @FastGTPSA(norm(sqrt(t^2) - t)) - @FastGTPSA(norm(csc(t)^2 - cot(t)^2 - 1)) - @FastGTPSA(norm(exp(log(t)) - t)) - @FastGTPSA(norm(log(exp(t)) - t)) - @FastGTPSA(norm(log(exp(t)) - exp(log(t)))) - @FastGTPSA(norm(log(t^2) - 2*log(t))) - @FastGTPSA(norm(5*log(t) - log(t^5) - 2*pi*im)) - @FastGTPSA(norm(t*log(5) - log(5^t))) - @FastGTPSA(norm(sinc(t/pi) - sin(t)/t)) - @FastGTPSA(norm(sinhc(t/pi) - sinh(t)/t)) - @FastGTPSA(norm(exp(im*t) - cos(t) - im*sin(t))) - @FastGTPSA(norm(sinh(t) - (exp(t) - exp(-t))/2)) - @FastGTPSA(norm(cosh(t) - (exp(t) + exp(-t))/2)) - @FastGTPSA(norm(tanh(t) - sinh(t)/cosh(t))) - @FastGTPSA(norm(csch(t) - 1/sinh(t))) - @FastGTPSA(norm(sech(t) - 1/cosh(t))) - @FastGTPSA(norm(coth(t) - cosh(t)/sinh(t))) - @FastGTPSA(norm(coth(t) - 1/tanh(t))) - @FastGTPSA(norm(cosh(t)^2 - sinh(t)^2 - 1)) - @FastGTPSA(norm(1 - tanh(t)^2 - sech(t)^2)) - @FastGTPSA(norm(coth(t)^2 - 1 - csch(t)^2)) - - @FastGTPSA(norm(asin(sin(t)) - t)) - @FastGTPSA(norm(acos(cos(t)) - t)) - @FastGTPSA(norm(atan(tan(t)) - t)) - @FastGTPSA(norm(acsc(t) - asin(1/t))) - @FastGTPSA(norm(asec(t) - acos(1/t))) - @FastGTPSA(norm(acot(t) - acot(1/t))) - @FastGTPSA(norm(asinh(sinh(t)) - t)) - @FastGTPSA(norm(acosh(cosh(t)) - t)) - @FastGTPSA(norm(atanh(tanh(t)) - t)) - @FastGTPSA(norm(acsch(t) - asinh(1/t))) - @FastGTPSA(norm(asech(t) - acosh(1/t))) - @FastGTPSA(norm(acoth(t) - acoth(1/t))) - @FastGTPSA(norm(asinc(t) - asin(t)/t)) - @FastGTPSA(norm(asinhc(t) - asinh(t)/t)) - @FastGTPSA(norm(erfc(t) - 1 + erf(t))) - @FastGTPSA(norm(erf(-t) + erf(t))) - @FastGTPSA(norm(angle(t) - atan(imag(t),real(t)))) - @FastGTPSA(norm(complex(t) - t)) + t[0] = 0.5+0.5im; t[[1]] = 2+2im; t[[2]] = 3+3im; t[[3]] = 4+4im; t[[4]] = 5+5im; t[[5]] = 6+6im + @FastGTPSA(norm(sin(t)^2+cos(t)^2 - 1)) < tol + @FastGTPSA(norm(1/sin(t) - csc(t))) < tol + @FastGTPSA(norm(1/cos(t) - sec(t))) < tol + @FastGTPSA(norm(1/tan(t) - cot(t))) < tol + @FastGTPSA(norm(sin(t)/cos(t) - tan(t))) < tol + @FastGTPSA(norm(cos(2*t) - cos(t)^2 + sin(t)^2)) < tol + @FastGTPSA(norm(sec(t)^2 - 1 - tan(t)^2)) < tol + @FastGTPSA(norm(sin(t/2) - sqrt((1-cos(t))/2))) < tol + @FastGTPSA(norm(cos(t/2) - sqrt((1+cos(t))/2))) < tol + @FastGTPSA(norm(sqrt(t^2) - t)) < tol + @FastGTPSA(norm(csc(t)^2 - cot(t)^2 - 1)) < tol + @FastGTPSA(norm(exp(log(t)) - t)) < tol + @FastGTPSA(norm(log(exp(t)) - t)) < tol + @FastGTPSA(norm(log(exp(t)) - exp(log(t)))) < tol + @FastGTPSA(norm(log(t^2) - 2*log(t))) < tol + @FastGTPSA(norm(5*log(t) - log(t^5) - 2*pi*im)) < tol + @FastGTPSA(norm(t*log(5) - log(5^t))) < tol + @FastGTPSA(norm(sinc(t/pi) - sin(t)/t)) < tol + @FastGTPSA(norm(sinhc(t/pi) - sinh(t)/t)) < tol + @FastGTPSA(norm(exp(im*t) - cos(t) - im*sin(t))) < tol + @FastGTPSA(norm(sinh(t) - (exp(t) - exp(-t))/2)) < tol + @FastGTPSA(norm(cosh(t) - (exp(t) + exp(-t))/2)) < tol + @FastGTPSA(norm(tanh(t) - sinh(t)/cosh(t))) < tol + @FastGTPSA(norm(csch(t) - 1/sinh(t))) < tol + @FastGTPSA(norm(sech(t) - 1/cosh(t))) < tol + @FastGTPSA(norm(coth(t) - cosh(t)/sinh(t))) < tol + @FastGTPSA(norm(coth(t) - 1/tanh(t))) < tol + @FastGTPSA(norm(cosh(t)^2 - sinh(t)^2 - 1)) < tol + @FastGTPSA(norm(1 - tanh(t)^2 - sech(t)^2)) < tol + @FastGTPSA(norm(coth(t)^2 - 1 - csch(t)^2)) < tol + + @FastGTPSA(norm(asin(sin(t)) - t)) < tol + @FastGTPSA(norm(acos(cos(t)) - t)) < tol + @FastGTPSA(norm(atan(tan(t)) - t)) < tol + @FastGTPSA(norm(acsc(t) - asin(1/t))) < tol + @FastGTPSA(norm(asec(t) - acos(1/t))) < tol + @FastGTPSA(norm(acot(t) - atan(1/t))) < tol + @FastGTPSA(norm(asinh(sinh(t)) - t)) < tol + @FastGTPSA(norm(acosh(cosh(t)) - t)) < tol + @FastGTPSA(norm(atanh(tanh(t)) - t)) < tol + @FastGTPSA(norm(acsch(t) - asinh(1/t))) < tol + @FastGTPSA(norm(asech(t) - acosh(1/t))) < tol + @FastGTPSA(norm(acoth(t) - atanh(1/t))) < tol + @FastGTPSA(norm(asinc(t/pi) - asin(t)/t)) < tol + @FastGTPSA(norm(asinhc(t/pi) - asinh(t)/t)) < tol + + @FastGTPSA(norm(erfc(t) - 1 + erf(t))) < tol + @FastGTPSA(norm(erf(-t) + erf(t))) < tol + @FastGTPSA(norm(angle(t) - atan(imag(t),real(t)))) < tol + @FastGTPSA(norm(complex(t) - t)) < tol # Make sure stack is 0: desc = unsafe_load(Base.unsafe_convert(Ptr{Desc}, unsafe_load(t.tpsa).d))