Joe Riel

9660 Reputation

23 Badges

20 years, 20 days

MaplePrimes Activity


These are replies submitted by Joe Riel

Using the Threads package was my first thought, however, I don't understand how it works. Consider the following. which uses a call to the OS sleep command to create a delay:

p := proc()
local self;
    self := Threads:-Self();
    printf("start thread %d\n", self);
    to 5 do
        #printf("thread %d: time = %a\n", self, time['real']());
        print(sprintf("thread %d: time = %a", self, time['real']()));
        system("sleep 2");
    end do;
    printf("finish thread %d\n", self);
end proc:

proc()
local id1,id2;
    id1 := Threads:-Create(p());
    id2 := Threads:-Create(p());
    Threads:-Wait(id1,id2);
    print("finished");
end proc();
start thread 1
start thread 2
                            "thread 1: time = .128"

                           "thread 1: time = 2.150"

                           "thread 1: time = 4.181"

                           "thread 1: time = 6.207"

                           "thread 1: time = 8.239"

finish thread 1
                            "thread 2: time = .150"

                           "thread 2: time = 12.296"

                           "thread 2: time = 14.316"

                           "thread 2: time = 16.337"

                           "thread 2: time = 18.358"

finish thread 2
                                  "finished"

Why are the print outputs not interleaved?  Does print not work with Threads?  If it matters, this is on a single-core machine.  If print is changed to a printf statement (see the commented-out line above), then it works as expected:

start thread 1
thread 1: time = .93e-1
start thread 2
thread 2: time = 2.119
thread 1: time = 2.112
thread 2: time = 4.138
thread 1: time = 6.163
thread 2: time = 8.177
thread 1: time = 10.197
thread 2: time = 12.216
thread 1: time = 14.231
thread 2: time = 16.246
finish thread 1
finish thread 2
                                  "finished"

Presumably the developer would also create various tests that verify the package, so maybe that is not an insurmountable problem.  A practical disadvantage to this technique is that any addition/deletion to the exports of a module requires updating two locations, a nuisance.  Regardless, I believe that the better solution is to restrict the use of use/uses to shortform=longform, that avoids the cyclic dependency issue as well as the more subtle problem of having an added export to the used module overwrite a local variable.

One way to break the cyclic dependency while still using use in each procedure assignment is to preassign skeleton modules that merely define the exports (somewhat analogous to a C header file).  Using your example,

restart;
m1 := module() export f1,f3; end module:
m2 := module() export f2; end module;

m1 := module()
export f1, f3;
    f1 := proc(x)
        use m2 in
            f2(x);
        end use;
    end proc;
    f3 := proc(x)
        sin(x);
    end proc;
end module:

m2 := module()
export f2;
    f2 := proc(x)
        use m1 in
            f3(x);
        end use;
    end proc;
end module:

m1:-f1(x);
                         sin(x)

 

That technique (using Arrays to generate cartesian products) is described at the link I provided, though not specialized to the problem at hand.  You'd probably want to use the 'storage=sparse' option to reduce the memory usage. That is, rather than creating an Array filled with the indices, do

intp:=()->[indices(Array(args,'storage=sparse'))];

That technique (using Arrays to generate cartesian products) is described at the link I provided, though not specialized to the problem at hand.  You'd probably want to use the 'storage=sparse' option to reduce the memory usage. That is, rather than creating an Array filled with the indices, do

intp:=()->[indices(Array(args,'storage=sparse'))];

Yes.  Even restricting yourself to Maple builtins doesn't necessarily avoid the issue---some builtins call back into the library. Note that it isn't just explicit globals that can cause problems.  Module locals act as global variables (more or less). In a call to seq, say seq(i/3, i = 1..10), the variable i has global context unless it is declared (in the calling procedure) as local.

Yes.  Even restricting yourself to Maple builtins doesn't necessarily avoid the issue---some builtins call back into the library. Note that it isn't just explicit globals that can cause problems.  Module locals act as global variables (more or less). In a call to seq, say seq(i/3, i = 1..10), the variable i has global context unless it is declared (in the calling procedure) as local.

The following should do what you want

iscoprime := proc(m::integer, n::integer)
    evalb(igcd(m,n) = 1);
end proc:

The following should do what you want

iscoprime := proc(m::integer, n::integer)
    evalb(igcd(m,n) = 1);
end proc:

The problem is that you are using 2D input.  The print statement doesn't necessarily work (I don't know the details) when in 2D mode. Try switching your input to 1D (Maple Input).

You are correct about the end if; I don't always test what I suggest, so typos may appear.

The problem is that you are using 2D input.  The print statement doesn't necessarily work (I don't know the details) when in 2D mode. Try switching your input to 1D (Maple Input).

You are correct about the end if; I don't always test what I suggest, so typos may appear.

Use a break statement in the inner loop.  That will terminate that loop but continue with the outer loop.

for i to 10 do
    for j to 10 do
         if some_condtition then break; end do;
   end do;
end do;

If you use a loop index variable you may not need a separate counter.  But you could do

cnt := 0
to 3 do
   cnt := cnt+1;
end do;

Use a break statement in the inner loop.  That will terminate that loop but continue with the outer loop.

for i to 10 do
    for j to 10 do
         if some_condtition then break; end do;
   end do;
end do;

If you use a loop index variable you may not need a separate counter.  But you could do

cnt := 0
to 3 do
   cnt := cnt+1;
end do;

My choice of moduli was poor; clearly I should have started at a reasonable value (i.e. not 2). To get negative solutions, assign the environmental variable mod the procedure mods:

restart;
eq := 5*x^2+11*x*y-5*y^2=11:
`mod` := mods;
sols := {seq({msolve(eq, ithprime(i))}, i=100..120)}:
sols := select(type, sols, set(set(name=integer))):
`intersect`(sols[]);
    {{x = 1, y = 1}, {x = 7, y = 18}, {x = 8, y = -3}, {x = 104, y = 269},  {x = 119, y = -46}}

Note that I didn't check whether a solution was found or the loop terminated.  You can either add a flag in the loop, or use a counter and check whether it exceeded the "to" value. For example,

if n = 361 then error "no solution found" end if;
First 117 118 119 120 121 122 123 Last Page 119 of 195