Joe Riel

9570 Reputation

23 Badges

18 years, 359 days

MaplePrimes Activity

These are answers submitted by Joe Riel

Here's the comparison without the algorithmic optimizations.
               +-------- timing -------+--------- memory ---------+
Procedure      | maple (s) | total (s) | used (MiB) | alloc (MiB) | gctimes
tp_original    |    22.69  |    23.08  |   246.61   |     36.43   |    6
tp_evalhf      |     2.06  |     2.16  |     0.00   |      0.00   |    0
tp_autocompile |     0.15  |     0.38  |     0.55   |      0.00   |    0
tp_compile     |     0.09  |     0.09  |     0.00   |      0.00   |    0
tp_compile looks like
tp_compile := Compile:-Compile( proc() ... end proc):
It doesn't run any faster than tp_autocompile, the timing difference is that the compilation time is not included in the run. To measure those accurately I'd need to execute them several times. Declaring the local counters as integers doesn't have any measurable effect (measured with multiple executions).
You can also use the autocompile option, which is frequently faste than calling evalhf. Also, there are two small optimizations you can make, not really pertinent to the broader topic. First, don't compute the square root, just compare against 100.0^2. Second, break out of the inner loop if Temp3 ≥ 100.0^2. Here are the revisions:
testproc3 := proc()
local tp;
    tp := proc()
    local i, j, k, total, Temp3, Temp1, Temp2;
        total := 0;
        for i to 100 do
            Temp1 := i*i;
            for j to 100 do
                Temp2 := Temp1+j*j;
                for k to 100 do
                    Temp3 := Temp2+k*k;
                    if Temp3 >= 10000.0 then
                    end if;
                    total := total+1;
                end do
            end do
        end do;
    end proc:
end proc:

testproc4 := proc()
local i, j, k, total, Temp3, Temp1, Temp2;
option autocompile;

    total := 0;
    for i to 100 do
        Temp1 := i*i;
        for j to 100 do
            Temp2 := Temp1+j*j;
            for k to 100 do
                Temp3 := Temp2+k*k;
                if Temp3 >= 10000.0 then
                end if;
                total := total+1;
            end do
        end do
    end do;
end proc:
With testproc1 and testproc2 being yours and Jacque's procedures, a comparison of the four gives
            +-------- timing -------+--------- memory ---------+
Procedure   | maple (s) | total (s) | used (MiB) | alloc (MiB) | gctimes
testproc1   |    22.97  |    24.74  |   247.12   |     37.68   |    6
testproc2   |     2.06  |     2.05  |     0.00   |      0.00   |    0
testproc3   |     1.04  |     1.03  |     0.00   |      0.00   |    0
testproc4   |     0.27  |     0.55  |     3.27   |      2.56   |    0
Slightly simpler is just
map(sin, [3,4,5]);
Another way to do this is
[seq(sin(x), x=[3,4,5])];
It builds a sequence and encloses it in a list.
The rest of your post is missing. If it includes a less-than sign, substitute the html equivalent `<' (not including the quotes). Note that the range in the seq assignment to datalist should be 1..n, not 0..n. Also where is plot2?
The way to do this is to compute the compute the intercept point (use yint := (ty*x-y*tx)/(x-tx)) then plot/write that value. I'm not sure what you want to plot it against, maybe just the index? Better would probably be against the distance of the incoming ray from the central axis. Here's how to do that (I added the x_vs_yint table to store the values; using a table, while not necessary here, is more efficient than building a list a term at a time):
mirror := x -> 8 - sqrt(64 - x^2):     # Mirror
slope := x -> x/sqrt(64 - x^2):        # Slope at each point on mirror
width := 5.0:                          # x = -slope..slope
height := 2 * width:                   # y = 0..height
n := 30:                               # number of light rays


blk := plot(mirror(x),
            x = -width..width, y = 0..height,
            axes = NONE, scaling = CONSTRAINED, color = black):

rays := {}:
x_vs_yint := table();
cnt := 0;

for i from 0 to n do
    x := -width + 2 * i * width/n:
    y := mirror(x):
    rays := rays union {line([x, height], [x, y])}:   # Incoming ray
    dr := slope(x):
    if (abs(dr) > 0.001) then          # if slope = 0 no outgoing ray
        m := (dr^2 - 1)/(2 * dr):
        ix := (height - y)/m:
        if ix < -width then
            tx := -width:
            ty := y + m * (tx - x):
        ix > width then
            tx := width:
            ty := y + m * (tx - x):
            ty := height:
            tx := (ty - y)/m + x:
        yint := (ty*x-y*tx)/(x-tx);
        cnt := cnt+1;
        x_vs_yint[cnt] := [x,yint];
        rays := rays union {line([x,y], [tx, ty])}:  # outgoing ray
rd  := display(rays, color = red, axes = NONE, scaling = CONSTRAINED):
display({blk, rd});
plot([seq(x_vs_yint[i], i=1..cnt)]);
Do not use with inside a procedure. It is for top-level use only. To access components of a module from a procedure or module, use the use ... end use statement or the uses phrase. You can also give the full path to the command. For example
myproc := proc(s::string)
uses StringTools;
end proc:
By default, LinearAlgebra uses, when possible, hardware floats to do Matrix computation of floats. You can explicitly turn this off by setting the environmental variable UseHardwareFloats false.
M := <<0.5|0.5>,<0.3|0.7>>;
                                    [0.5    0.5]
                               M := [          ]
                                    [0.3    0.7]
                [0.400000000000000024    0.599999999999999978]
                [                                            ]
                [0.359999999999999986    0.639999999999999904]
UseHardwareFloats := false:
                               [0.400    0.600]
                               [              ]
                               [0.360    0.640]
Another possibility is to use the older linalg package, but you need to convert to matrices.
m := convert(M,matrix):
                                [0.40    0.60]
                                [            ]
                                [0.36    0.64]
How about posting a snippet of code that illustrates the problem. You also might want to try using Array rather than array, but its hard to say without seeing what you are doing.
A better approach would be to delete them all in one call.
M := DeleteRow(M, [seq(`if`(M[i,2]=M[i,3],i,NULL), i=1..RowDimension(M))]);
Another way to do this is to keep the rows that are "good".
M := M[[seq(`if`(M[i,2]=M[i,3],NULL,i), i=1..RowDimension(M))], [1..-1]];
To insert a less-than sign in html use &lt;.
A do loop should be no less efficient here:
for i to RowDimension(M) do
   if M[i,2] = M[i,3] then M[i,1] := 0; end if;
end do:
One way is
P := convert(P,units,Torr);
I'm not sure that's what you really want, _C1 is normally considered a constant depending on the initial conditions (which you didn't supply) but you can use solve to solve for _C1:
solve(%, _C1);
Edited after posting. Modified procedure to permit strings as indices. What you want is doable, at least using the Maple 10 Standard gui, however, it requires the use of some undocumented procedures in the Typesetting package. My knowledge of these is scanty. The following seems to do what you desire. By default it inserts an extra space following the comma that separates items. If you pass a nonnegint as an index to the procedure, it will use that number of spaces. If you pass a string as the index, it will insert that string between each element.
PrintExtraSpace := proc()
local a, spaces;
uses Typesetting, ListTools;
description "print arguments with extra space following commas";
    if not IsWorksheetInterface('Standard') then
        return args;
    end if;
    if procname::indexed then
        spaces := op(procname);
        if [spaces]::[nonnegint] then
            spaces := cat(",", " "$spaces);
        elif not [spaces]::[string] then
            error "index to procedure must be a nonnegative integer or a string";
        end if;
        spaces := ",  ";
    end if;
    mrow(JoinSequence([seq(Typeset(EV(a)), a in args)]
                      , mi(spaces))[]);
end proc:
For two spaces do
PrintExtraSpace( ... );
For more space do
PrintExtraSpace[5]( ... );
If you want some other separator, including the comma, insert it as a string in the index
PrintExtraSpace[";---"]( ... )
Note that you won't be able to usefully copy and paste the output. If you compare this output to the standard output, you'll notice that the inserted comma is bolder.
The LinearAlgebra package uses Matrices and Vectors, not matrices and vectors. They are different beasts. The linalg package, on the other hand, uses matrices and vectors, not Matrices and Vectors. Matrices and Vectors are a newer Maple construct. In your example you could do
A:= Matrix(3,3,[$1..9]);
You could also do
A . 3;
3 . A;
or even
Yes, it is possible. In 2D mode type Delta, Ctrl-Shift-Space x. The 'Ctrl-Shift-Space' sequence is for the linux OS, I'm not sure about Windows. Check the Help->Quick Reference "2D Math Editing Operations, Keyboard Shortcuts and Operations" (last line in that subsection).
First 107 108 109 110 111 112 113 Page 109 of 114