Carl Love

Carl Love

28010 Reputation

25 Badges

12 years, 290 days
Himself
Wayland, Massachusetts, United States
My name was formerly Carl Devore.

MaplePrimes Activity


These are answers submitted by Carl Love

My original Answer was wrong because I made M^*.M a symmetric matrix when actually it's hermitian. I thank dharr for pointing out my error. Here's a corrected Answer. The incorrect one is at the bottom of this Answer for the sake of continuity of reading.

I will use for your because the default sans-serif font on MaplePrimes essentially makes l unreadable. The trick to doing your problem is expressing L as Lx + I*Ly where Lx and Ly are assumed real, and simplifying conjugated expressions with simplify(..., conjugate) and evalc.

In Maple, M^%H (or M^*) is the HermitianTranspose of M, and A.B is the matrix product of matrices A and B. Spelling out MatrixMatrixMultiply or HermitianTranspose is unnecessary.

Because I use evalc (which assumes variables are real), the assume(a::complex) is needed.

The final eigenvectors below can be further simplified, but it requires subtlety.

restart:

interface(showassumed= 0):

assume(Lx::real, Ly::real, a::complex, k>0, Lx^2+Ly^2 < 1);

L:= Lx+I*Ly:

B:= simplify(k*(1-L*conjugate(L)));

-k*(Lx^2+Ly^2-1)

M:= <L-B, -a*B; 0, L+B>;

Matrix(2, 2, {(1, 1) = Lx+I*Ly+k*(Lx^2+Ly^2-1), (1, 2) = a*k*(Lx^2+Ly^2-1), (2, 1) = 0, (2, 2) = Lx+I*Ly-k*(Lx^2+Ly^2-1)})

MS:= simplify(evalc~(M^%H.M), conjugate);

Matrix(2, 2, {(1, 1) = (Lx^2+Ly^2-1)^2*k^2+2*Lx*(Lx^2+Ly^2-1)*k+Lx^2+Ly^2, (1, 2) = a*k*(Lx^2+Ly^2-1)*(Lx-I*Ly+Lx^2*k+Ly^2*k-k), (2, 1) = k*(Lx^2+Ly^2-1)*conjugate(a)*(Lx+I*Ly+k*(Lx^2+Ly^2-1)), (2, 2) = (Lx^2+Ly^2-1)^2*k^2*abs(a)^2+Ly^2+(Lx-k*(Lx^2+Ly^2-1))^2})

EV:= LinearAlgebra:-Eigenvectors(MS, output= vectors);

Matrix(2, 2, {(1, 1) = -2*a*((-Lx^2-Ly^2+1)*k+I*Ly-Lx)/(-sqrt((Lx^2+Ly^2-1)^2*k^2*abs(a)^4+(4*(Lx^2+Ly^2-1)^2*k^2+4*Lx^2+4*Ly^2)*abs(a)^2+16*Lx^2)+k*(Lx^2+Ly^2-1)*abs(a)^2-4*Lx), (1, 2) = -2*a*((-Lx^2-Ly^2+1)*k+I*Ly-Lx)/(sqrt((Lx^2+Ly^2-1)^2*k^2*abs(a)^4+(4*(Lx^2+Ly^2-1)^2*k^2+4*Lx^2+4*Ly^2)*abs(a)^2+16*Lx^2)+k*(Lx^2+Ly^2-1)*abs(a)^2-4*Lx), (2, 1) = 1, (2, 2) = 1})

eval(map(simplify, EV, {L=`&ell;`, Lx-I*Ly= CL}), CL= conjugate(`&ell;`));

Matrix(2, 2, {(1, 1) = -2*a*(`&ell;`*conjugate(`&ell;`)*k+conjugate(`&ell;`)-k)/(k*(-`&ell;`*conjugate(`&ell;`)+1)*abs(a)^2+sqrt(k^2*(`&ell;`*conjugate(`&ell;`)-1)^2*abs(a)^4+(4*k^2*(`&ell;`*conjugate(`&ell;`)-1)^2+4*`&ell;`*conjugate(`&ell;`))*abs(a)^2+4*(`&ell;`+conjugate(`&ell;`))^2)+2*conjugate(`&ell;`)+2*`&ell;`), (1, 2) = 2*a*(`&ell;`*conjugate(`&ell;`)*k+conjugate(`&ell;`)-k)/(k*(`&ell;`*conjugate(`&ell;`)-1)*abs(a)^2+sqrt(k^2*(`&ell;`*conjugate(`&ell;`)-1)^2*abs(a)^4+(4*k^2*(`&ell;`*conjugate(`&ell;`)-1)^2+4*`&ell;`*conjugate(`&ell;`))*abs(a)^2+4*(`&ell;`+conjugate(`&ell;`))^2)-2*conjugate(`&ell;`)-2*`&ell;`), (2, 1) = 1, (2, 2) = 1})

 

Download SymbEigenvectors.mw

 

Original incorrect worksheet:

restart:

L:= Lx+I*Ly:

B:= simplify(k*(1-L*conjugate(L))) assuming real;

-k*(Lx^2+Ly^2-1)

M:= <L-B, -a*B; 0, L+B>;

Matrix(2, 2, {(1, 1) = Lx+I*Ly+k*(Lx^2+Ly^2-1), (1, 2) = a*k*(Lx^2+Ly^2-1), (2, 1) = 0, (2, 2) = Lx+I*Ly-k*(Lx^2+Ly^2-1)})

MS:= Matrix(evalc~(M^%H.M), shape= symmetric) assuming a::complex;

Matrix(2, 2, {(1, 1) = (Lx+k*(Lx^2+Ly^2-1))^2+Ly^2, (1, 2) = a*((Lx+k*(Lx^2+Ly^2-1))*k*(Lx^2+Ly^2-1)-I*Ly*k*(Lx^2+Ly^2-1)), (2, 1) = a*((Lx+k*(Lx^2+Ly^2-1))*k*(Lx^2+Ly^2-1)-I*Ly*k*(Lx^2+Ly^2-1)), (2, 2) = conjugate(a*k*(Lx^2+Ly^2-1))*a*k*(Lx^2+Ly^2-1)+(Lx-k*(Lx^2+Ly^2-1))^2+Ly^2})

EV:= LinearAlgebra:-Eigenvectors(MS, output= vectors) assuming (Lx,Ly)::~real, abs(L)^2 < 1, k>0;

Matrix(2, 2, {(1, 1) = -2*a*((-Lx^2-Ly^2+1)*k+I*Ly-Lx)/(-sqrt(k^2*(Lx^2+Ly^2-1)^2*abs(a)^4-8*k*Lx*(Lx^2+Ly^2-1)*abs(a)^2+4*a^2*k^2*(Lx^2+Ly^2-1)^2-8*a^2*(I*Ly-Lx)*(Lx^2+Ly^2-1)*k+(4*a^2+16)*Lx^2-(8*I)*a^2*Lx*Ly-4*Ly^2*a^2)+k*(Lx^2+Ly^2-1)*abs(a)^2-4*Lx), (1, 2) = -2*a*((-Lx^2-Ly^2+1)*k+I*Ly-Lx)/(sqrt(k^2*(Lx^2+Ly^2-1)^2*abs(a)^4-8*k*Lx*(Lx^2+Ly^2-1)*abs(a)^2+4*a^2*k^2*(Lx^2+Ly^2-1)^2-8*a^2*(I*Ly-Lx)*(Lx^2+Ly^2-1)*k+(4*a^2+16)*Lx^2-(8*I)*a^2*Lx*Ly-4*Ly^2*a^2)+k*(Lx^2+Ly^2-1)*abs(a)^2-4*Lx), (2, 1) = 1, (2, 2) = 1})

eval(map(simplify, EV, {L=`&ell;`, Lx-I*Ly= CL}), CL= conjugate(`&ell;`));

Matrix(2, 2, {(1, 1) = -2*a*(k*`&ell;`*conjugate(`&ell;`)+conjugate(`&ell;`)-k)/(k*(-`&ell;`*conjugate(`&ell;`)+1)*abs(a)^2+sqrt(k^2*(`&ell;`*conjugate(`&ell;`)-1)^2*abs(a)^4-4*k*(`&ell;`+conjugate(`&ell;`))*(`&ell;`*conjugate(`&ell;`)-1)*abs(a)^2+4*a^2*(`&ell;`*conjugate(`&ell;`)-1)^2*k^2+8*a^2*conjugate(`&ell;`)*(`&ell;`*conjugate(`&ell;`)-1)*k+4*`&ell;`^2+8*`&ell;`*conjugate(`&ell;`)+4*conjugate(`&ell;`)^2*(a^2+1))+2*conjugate(`&ell;`)+2*`&ell;`), (1, 2) = 2*a*(k*`&ell;`*conjugate(`&ell;`)+conjugate(`&ell;`)-k)/(k*(`&ell;`*conjugate(`&ell;`)-1)*abs(a)^2+sqrt(k^2*(`&ell;`*conjugate(`&ell;`)-1)^2*abs(a)^4-4*k*(`&ell;`+conjugate(`&ell;`))*(`&ell;`*conjugate(`&ell;`)-1)*abs(a)^2+4*a^2*(`&ell;`*conjugate(`&ell;`)-1)^2*k^2+8*a^2*conjugate(`&ell;`)*(`&ell;`*conjugate(`&ell;`)-1)*k+4*`&ell;`^2+8*`&ell;`*conjugate(`&ell;`)+4*conjugate(`&ell;`)^2*(a^2+1))-2*conjugate(`&ell;`)-2*`&ell;`), (2, 1) = 1, (2, 2) = 1})

``

Below, I have put your data in exactly the same order as you gave it; however, I've grouped it with square brackets and commas. Please note where the brackets are; the pattern should be obvious. Line breaks, spacing, and indentation are irrelevant; they're only used to enhance readability.

Pts:= [
    [
        [80, 1, 1.80074340195803263], [80, 2, 1.79160585795803287], [80, 3, 1.7805446209580329], 
        [80, 4, 1.76755968995803269], [80, 5, 1.75265106495803280], [80, 6, 1.73581874695803272],
        [80, 7, 1.71706273595803272]
    ],
    [                        
        [85, 1, 1.71097991748770582], [85, 2, 1.70184237348770577], [85, 3, 1.69078113648770581], 
        [85, 4, 1.67779620548770559], [85, 5, 1.66288758048770571], [85, 6, 1.64605526248770562],
        [85, 7, 1.62729925148770591]
    ],                          
    [
       [95, 1, 1.53550477309879818], [95, 2, 1.52636722910871089], [95, 3, 1.51530599205435690], 
       [95, 4, 1.50232106105435669], [95, 5, 1.48741243605435680], [95, 6, 1.47058011805435672], 
       [95, 7, 1.45182410705435672]
    ],
    [                    
       [100, 1, 1.44826461660029512], [100, 2, 1.43912707260029623], [100, 3, 1.42806583560029569],               [100, 4, 1.41508090460029576], [100, 5, 1.40017227960029588], [100, 6, 1.38333996160029579],       
       [100, 7, 1.36458395060029579]
    ]
]: 
plots:-display(PLOT3D(MESH(Pts)), labels= [x,y,z]);

Note that PLOT3D and MESH are all uppercase letters. Some help for them can be found at ?plot,structure; however, the best way to learn about them is to deconstruct the results of plot3d (lowercase) commands with op.

An equivalent command, producing exactly the same plot, is

plots:-surfdata(Pts, labels= [x,y,z])

Either way, the trickier part is gettiing the data arranged correctly in a list of lists of lists (as shown above) or a 3D-Array (as shown by acer). Once that's done, displaying it is easy.

 

The trick is to insert a fake symbolic exponent and substitute 1 for it after the extraction, like this:

Powers:= (e, T::type)-> local One;
    eval(
        indets(combine(evalindets(e, T, `^`, One), power), T^anything),
        One= 1
    )
:
e:=_C1^2+_C1+_C1*_C2^3+a+b:
Powers(e, suffixed(_C, nonnegint));
                       /        2     3\ 
                      { _C1, _C1 , _C2  }
                       \               / 

By the way, suffixed(_C, ...is a subtype of symbol, so your And(symbol, ...) is redundant.

It's not a caching issue. What's happening is that the elapsed time between your calls to randomize is much shorter than the "ticks" of the clock. There's never a need to call randomize more than once. Indeed, the effect of calling randomize twice in a short time period is to reset the random-number generator to a specific entry in its sequence, so that's about as unrandomized as you can get.

My feeling about randomize is that it should only be called at the top level, never in a procedure.

Also, there's never a need to pass randomize a custom clock value. The simple call randomize() (with no arguments) already uses a clock-based value that's sufficient for any purpose.

Like this:

collect(T, indets(T, function));
                   
f(x) + 3 + (b + 1) g(x)

@Kitonum is correct that shading regions of polar plots is difficult in Maple, and a "polygon" approach is needed. Here's a way to do it that's perhaps more intuitive than his: I extract the polygon vertices directly from the output of polarplot commands. There's no need to look at the numerical vertices; it's all done rather automatically. Some additional benefits of my approach are that I put the plots on Maple's polar axes rather than Cartesian axes, and no explicit coordinate conversions are required.

I also show three distinct ways to get the area.

restart:

interface(prompt= "")
:

(r1, r2):= (-6*cos(theta),  2-2*cos(theta))
:

#Find theta values at the intersections:
theta__1:= rhs(solve({r1=r2, theta >= 0, theta <= Pi})[]);

(2/3)*Pi

I will extract the point-data matrices (rtables) for two of the relevant arcs for two purposes:
    1. To make filled polygon plots;
    2. To get the area of those polygons via the Shoelace formula (simply to verify integration accuracy). The formula is given below, but you don't
        need to understand it to understand the rest of this worksheet.

 

The point data is stored in Cartesian (rather than polar) coordinates; however, you don't need to know that to understand this worksheet.

(Circle__arc, Cardioid__arc):= (op@indets)~(
    plots:-polarplot~([r1, r2], theta=~ [Pi/2..theta__1, theta__1..Pi]),
    rtable
)[]:
#Reconnect stray end to origin to close the polygon:
Cardioid__arc:= <Cardioid__arc, <0|0>>:

The whole plot:

plots:-display(
    plots:-polarplot~(
        [r1, r2], theta=~ [Pi/2..Pi, 0..Pi], color=~ [red, blue],
        thickness= 2,
        legend=~ [r1, r2], coordinateview= [default, 0..Pi]
    ),
    plots:-polygonplot~(
        [Circle__arc, Cardioid__arc], transparency= .5,
        color=~ [pink, blue], legend=~ ["Area 1", "Area 2"]
    )
);

We want the area of the pink region + the area of the blue region, times 2. We can get that directly like this:

2*(Int(r1^2/2, theta= Pi/2..theta__1) + Int(r2^2/2, theta= theta__1..Pi)):
% = value(%);

2*(Int(18*cos(theta)^2, theta = (1/2)*Pi .. (2/3)*Pi))+2*(Int((1/2)*(2-2*cos(theta))^2, theta = (2/3)*Pi .. Pi)) = 5*Pi

An indirect way to get the area, just as easy, is the area of the circle minus the area the part of the circle outside the cardioid:

2*(Int(r1^2/2, theta= Pi/2..Pi) - Int(r1^2/2-r2^2/2, theta= theta__1..Pi)):
% = value(%);

2*(Int(18*cos(theta)^2, theta = (1/2)*Pi .. Pi))-2*(Int(18*cos(theta)^2-(1/2)*(2-2*cos(theta))^2, theta = (2/3)*Pi .. Pi)) = 5*Pi

And a way to approximate the area is the "Shoelace formula", which gives the area of any polygon simply from the Cartesian coordinates of its vertices. I do this because its easy since we already have the polygons.

Shoelace:= (XY::Matrix)->
    add(XY[..,1]*~XY[[2..,1],2]-XY[..,2]*~XY[[2.., 1],1])/2
:
2*Shoelace(<Circle__arc, Cardioid__arc>) = evalf(5*Pi);

HFloat(15.707812810646793) = 15.70796327

 

Download PolarArea.mw

Use sort with this key:

sort(F, key= [f-> subs(0= infinity, degree~(f, [x4,x3,x2,x1])), nops])

I assume that by "degree of nonlinearity in x4" you mean nothing more than simply "degree in x4 (regardless of the presence of other variables)". If that's not what you mean, let me know. Also, this solution assumes that the polynomials are expanded.

Change
yB_:= y -> sol4[1]:
to
yB_:= MakeFunction(sol4[1], y):

You are correct that the y in the solution is not being seen. This is because there is no y explicitly on the right side of the arrow. In order to make a non-explicit variable into a procedure parameter, you need to use MakeFunction instead of ->.

Creating the set of equations can be done as simply as this:

{seq}(Matrix(2, symbol= a) - Matrix(2, symbol= b) =~ Matrix(2, shape= identity));
       
{a[1, 1] - b[1, 1] = 1, a[1, 2] - b[1, 2] = 0, a[2, 1] - b[2, 1] = 0, a[2, 2] - b[2, 2] = 1}

@michaelvio 

The vast majority of the slowness that you were experiencing was due to your use of int (symbolic integration) versus Int (numeric integration, when it's used in the context that you were using).

It's true that using a larger epsilon and a smaller numpoints will save some time, but that savings is infinitesimal in this case. I recommend that you remove both options so that those things will be done at their default values (although epsilon= 1e-6 is sufficient for plotting purposes).

You should also set Digits:= 15 right after the restart at the top of the worksheet. The extra precision makes a huge difference in the final plot, and the extra time needed isn't even noticeable.

To construct the function J1 as you just described, all that you need to do is

J1:= unapply(subs(x0= 1/t0, J), t0);

This is your last plot at the default Digits:= 10:

And this is using Digits:= 15:

It's a similar issue as with your recent Question regarding applying eval to Int or Intateval uses rules, usually to ensure the mathematical validity of the proposed substitution. The rule in this case is the procedure `eval/limit`. To create a more-sophisticated rule, read the procedure (showstat(`eval/limit`), it's a fairly easy read with only a moderate amount of Maple knowledge, and it's only 42 lines (Maple 2023)) and either write an overload or, perhaps, modify the procedure directly (ToInertFromInert).

If you'd like it to follow rules additional to what's already in the procedure, and you can state them for me with a moderate amount of mathematical precision and generality, I may be able to suggest a way to code it. 

Let's consider your examples individually:

1. e:= A+B*limit(f(x), x= infinity);  eval(e, limit(f(x), x= infinity)= 1);
This case doesn't involve changing anything inside any limit. Thus, the rule isn't used (verified by using trace(`eval/limit`)), and you got your expected result.

2. e:= A+B*limit(2*f(x), x= infinity);  eval(e, limit(f(x), x= infinity)= 1);
In this case you're asking it to evaluate an expression containing a limit by using information about another limit (albeit, a very closely related one); the eval rule will be used. I think that the mathematical rule (i.e., abstract, not Maple) that you're implicitly invoking here is always valid, although I'm not 100% sure about all weird "corner cases", domains other than 2-sided real, and multivariate (more than one bound variable (e.g., limit(..., (x,y)= ...)) cases. That rule, stated generally, is that factors that don't depend on the bound variable(s) can be factored out of the limit. Command expand will do this, so a quick solution is 
eval(expand(e), limit(f(x), x= infinity)= 1)

[to be continued]

The correct command is is

is(sqrt(3) < 3);

Presumably it just expands things to a sufficient number of decimal places to make sure.

You wrote:

  • Should one then use is(n>=m) instead of evalb(n>=m) always?

No! That's inefficient. evalb is builtin (kernel code rather than Maple). is is a highly symbolic command written in Maple. In the vast majority of cases, you know a priori that both sides are type numeric, and is isn't needed.

  • I can also always apply evalf() on each side before. But this seems like an overkill to me.

I think that's the approach that is takes, and it might increase Digits if the user's set value is not high enough to make absolutely sure of the inequality.

I said that I could probably come up with something better for large n and < < n, and here it is.

To make the algorithm fast, there are three things to avoid:

  1. finding all the large prime factors of n when that is difficult to do,
  2. finding all the divisors and then filtering them when the number of divisors is large,
  3. checking every positive integer < m when m is large.

The command ifactors(n, easy) finds only the prime factors that are easy to find.

Small Divisors of Integers

A fast algorithm for finding the divisors less than some upper bound of a large integer

 

Text and code author: Carl Love <carl.j.love@gmail.com> 2024-Sept-27

 

restart
:

interface(prompt= "")
:

To understand my SmallDivisors algorithm, you need to understand the output of the integer factorization command ifactors(..., easy). So, for example, I'll build an integer n that has an easy-to-factor part and a hard-to-factor part and apply the 'easy' algorithm to it. I believe (although I'm not absolutely sure) that the 'easy' algorithm will find any prime factor < 2^22. It will often also find nontrivial prime factors larger than that.

p1:= prevprime(2^25); 2^25-p1;

33554393

39

p2:= nextprime(p1);

33554467

p3:= nextprime(p2);

33554473

n:= (2*3*5*7)^32*(p1*p2*p3)^2;

292090706291643821582093796327445337477364073600065563995291265004658240987511107950432900000000000000000000000000000000

The hard-to-factor part will be p2*p3.

p2*p3;

1125902456980891

1+ilog10(%); #Count its base-10 digits.

16

ifactors(n, easy);

[1, [[2, 32], [3, 32], [5, 32], [7, 32], [33554393, 2], [_c16_1, 2]]]

So, the above says that n = 1 * 2^32* 3^32 * 5^32 * 7^32 * (2^25 - 39)^2 * "a 16-digit composite"^2.

 

Here's the procedure:

(*
Fast algorithm to return the divisors of n less than m.

This procedure may return a syntax error if entered as 2D Input.
Please use 1D input (aka, Maple Input or "plaintext").
*)
SmallDivisors:= proc(n::And(posint, Not(1)), m::And(posint, Not(1)))
description "divisors of n less than m";
option `Author: Carl Love <carl.j.love@gmail.com> 2024-Sept-28`;
local
    F:= ifactors(n, 'easy')[2],
    PF:= remove(type, F, [name,posint]),
    P:= op~(1,PF), #the prime factors
    #Get max possible exponent for each prime:
    E:= min~(op~(2,PF), trunc~(evalhf~(ln(m)/~(ln~(P))))),
    r:= {1}, p, k, D, d
;
    if ilog2(m) > 21 and F[-1][1]::name and E[-1] <> 0 then
        WARNING("Some divisors < %1 may be missing", m)
    fi;
    for k,p in P do
        D:= r[];
        r union= {to E[k] do D:= for d in D while d*p < m do d*p od od}    
    until E[k]=0
end proc
:

Use it on Kitonum's example:

d1:= CodeTools:-Usage(SmallDivisors(10^100+1, 10^6)): d1;

memory used=301.66KiB, alloc change=0 bytes, cpu time=0ns, real time=101.00ms, gc time=0ns

{1, 73, 137, 401, 1201, 1601, 10001, 29273, 54937, 87673, 116873, 164537, 219337, 481601, 642001}

Compare with Kitonum's method, which obviouly has time complexity O(m):

Brute:= (n,m)-> local k; {seq(`if`(irem(n,k)=0, k, NULL), k= 1..m-1)}:

d2:= CodeTools:-Usage(Brute(10^100+1, 10^6)): d2;

memory used=146.08MiB, alloc change=52.63MiB, cpu time=47.00ms, real time=618.00ms, gc time=0ns

{1, 73, 137, 401, 1201, 1601, 10001, 29273, 54937, 87673, 116873, 164537, 219337, 481601, 642001}

Compare using a larger upper bound m:

d1:= CodeTools:-Usage(SmallDivisors(10^99+1, 10^7)): d1;

memory used=214.85KiB, alloc change=0 bytes, cpu time=0ns, real time=6.00ms, gc time=0ns

{1, 7, 11, 13, 19, 23, 77, 91, 121, 133, 143, 161, 209, 247, 253, 299, 437, 847, 1001, 1463, 1573, 1729, 1771, 2093, 2299, 2717, 2783, 3059, 3289, 4093, 4807, 5681, 8779, 11011, 16093, 19019, 19481, 23023, 28651, 29887, 33649, 36179, 39767, 45023, 52579, 52877, 53209, 61453, 62491, 77767, 94139, 96569, 114127, 166801, 201917, 209209, 253253, 315161, 368053, 370139, 372463, 437437, 495253, 544369, 578369, 585299, 658973, 675983, 683527, 687401, 798889, 855437, 999001, 1010971, 1035529, 1062259, 1167607, 1209317, 1223807, 1255397, 1413419, 1788641, 1834811, 2168413, 2221087, 2624921, 3466771, 3836423, 4048583, 4097093, 4784689, 4811807, 5988059, 6362059, 6438289, 6993007, 7076797, 7248703, 7435813, 7518797, 8465219, 8566649, 8787779, 9409807}

d2:= CodeTools:-Usage(Brute(10^99+1, 10^7)): d2;

memory used=1.22GiB, alloc change=96.66MiB, cpu time=1.98s, real time=7.04s, gc time=1.53s

{1, 7, 11, 13, 19, 23, 77, 91, 121, 133, 143, 161, 209, 247, 253, 299, 437, 847, 1001, 1463, 1573, 1729, 1771, 2093, 2299, 2717, 2783, 3059, 3289, 4093, 4807, 5681, 8779, 11011, 16093, 19019, 19481, 23023, 28651, 29887, 33649, 36179, 39767, 45023, 52579, 52877, 53209, 61453, 62491, 77767, 94139, 96569, 114127, 166801, 201917, 209209, 253253, 315161, 368053, 370139, 372463, 437437, 495253, 544369, 578369, 585299, 658973, 675983, 683527, 687401, 798889, 855437, 999001, 1010971, 1035529, 1062259, 1167607, 1209317, 1223807, 1255397, 1413419, 1788641, 1834811, 2168413, 2221087, 2624921, 3466771, 3836423, 4048583, 4097093, 4784689, 4811807, 5988059, 6362059, 6438289, 6993007, 7076797, 7248703, 7435813, 7518797, 8465219, 8566649, 8787779, 9409807}

evalb(d1 = d2);

true

Now let's consider a number with a great many small divisors. The n1 below has 3^14 (~4.8 million) divisors.

n1:= mul(ithprime(k), k= 1..14)^2;

171158644061440576710668800200900

d3:= CodeTools:-Usage(SmallDivisors(n1, 10^9)): nops(d3);

memory used=10.56MiB, alloc change=4.27MiB, cpu time=0ns, real time=79.00ms, gc time=0ns

133547

d4:= CodeTools:-Usage(select(`<`, NumberTheory:-Divisors(n1), 10^9)):

memory used=0.86GiB, alloc change=206.21MiB, cpu time=3.44s, real time=6.41s, gc time=2.89s

evalb(d3=d4);

true

SmallDivisors has comparable performance with NumberTheory:-Divisors when all divisors are requested:

d5:= CodeTools:-Usage(SmallDivisors(n1, n1+1)): nops(d5)=3^14;

memory used=443.29MiB, alloc change=118.64MiB, cpu time=2.00s, real time=4.19s, gc time=1.70s

4782969 = 4782969

d6:= CodeTools:-Usage(NumberTheory:-Divisors(n1)): nops(d6);

memory used=322.98MiB, alloc change=-2.08MiB, cpu time=3.33s, real time=3.77s, gc time=3.16s

4782969

The following number has 15! (~1.3 trillion) divisors, so it would be infeasible to apply NumberTheory:-Divisors to it due to memory limitation. Howver, SmallDivisors can easily find all divisors less than 1 trillion.

n2:= mul(ithprime(i)^(15-i), i= 1..14);

222046261244808869776040900239313953120666458401987626347805929809038681543479663134628000000000000

d7:= CodeTools:-Usage(SmallDivisors(n2, 10^12)):
nops(d7), d7[-1], ifactor(d7[-1]);

memory used=456.89MiB, alloc change=27.00MiB, cpu time=2.03s, real time=3.45s, gc time=1.86s

6055806, 999999663336, ``(2)^3*``(3)^5*``(17)*``(23)*``(31)^2*``(37)^2

 

 

 

 

Download SmallDivisors.mw

This may be suitable for you:

select(`<`, Divisors(n), m)

Surely it's more efficient than what you were doing. For an easy-to-factor n >> 2^64 and m << sqrt(n), I could probably come up with something even better.

My guess is that you actually want the simplified product of an arbitrary number of factors of T[r]*P[r] --

T[1]*P[1]*...*T[n]*P[n]

-- because otherwise your Question would be exceedingly trivial. But first, you should stop trying to use an index (your r) as a parameter. Maple does allow the use of indices as parameters, but it's a somewhat more advanced topic than your current level of Maple knowledge. So, for now, let's just make r an ordinary parameter:

T:= r-> exp(r+1);  P:= r-> exp(r-1);

Your product can be represented as an inert product with the Product command:

Product(T(r)*P(r), r= 1..3);

             

Now, here's the non-trivial (but still conceptually easy) part: Make the upper bound, 3, arbitrary, and make the product non-inert by using product (lowercase):

product(T(r)*P(r), r= 1..n);

             

Of course that can be greatly simplified:

simplify(%);

             


By the way, can anybody give me an English word that's actually used in mathematical prose that completes this formal two-level analogy?:

(Addition is to summation as multiplication is to __?__)
as in Maple
(add is to sum as mul is to product).

That word, if it exists, would replace "products" in this Answer's Title.

3 4 5 6 7 8 9 Last Page 5 of 394