I wanted to return the obtained function output into a variable that I added into the RECORD using TRANSFORM. What does this error in image here mean? - ecl

distcomp (REAL4 lat1, REAL4 lon1,REAL4 lat2, REAL4 lon2, REAL4 dist) := FUNCTION
REAL4 lo1 := lon1/57.29577951;
REAL4 lo2 := lon2/57.29577951;
REAL4 la1 := lat1/57.29577951;
REAL4 la2 := lat2/57.29577951;
REAL4 dlon := lo2 - lo1;
REAL4 dlat := la2 - la1;
REAL4 a := sin(dlat / 2)*sin(dlat / 2) + cos(la1) * cos(la2) * sin(dlon/2)*sin(dlon/ 2);
REAL4 c := 2 * asin(sqrt(a));
REAL4 di := 6371 * c;
RETURN IF( di <= dist, 1,0);
END;
ProjResult := PROJECT(MENTORS,
TRANSFORM(New_MentorsRaw_Rec,
SELF.Qualify := distcomp(LEFT.Latitude,LEFT.Longitude, Latitude,
Longitude, Distance); // I'm getting error here in this line
SELF.RecCount := 0;
SELF := LEFT // Assign everything from left recordset
));
-> I'm getting error at the line SELF.Qualify and the error goes like this
" ERROR - syntax error near ')':expected:="

This error usually means that the syntax check has found definitions in your code that have not been defined before they were referenced in the code. In your case, it appears that the third (i.e, "latitude"), fourth (i.e., "longitude"), and fifth (i.e., "distance") input parameters of your distcomp function call in SELF.Qualify are falling under this case. These input parameters would either need to be prefixed with "LEFT." in case they are values coming from the MENTORS recordset (* see note below) or be defined beforehand in the code with their respective values.
* Word of caution: If I understood correctly, you trying to have two different pairs of latitude and longitude values to be used as an input of the distcomp function call in SELF.Qualify. Since the PROJECT() function processes one record at a time, in its associated TRANSFORM() function you will need to make sure you make a distinction between the names of the two different latitudes and longitudes being processed. This usually means that the MENTORS recordset will need to have these two different pair of values under different column names (such as latitude1, longitude1, latitude2 and longitude 2). Another alternative would be to replace the PROJECT() function by another function that processes two records at a time, such as an ITERATE() or even a JOIN() function (in the latter case you will also need a second recordset).

Related

Special For-Loop in Pascal

I work with a current software for the simulation of power plant processes. Smaller scripts can be written within the software for automation, these scripts are based on Pascal and own function libraries. Was simply retained after the initial release 20 years ago.
My simple script transfers values from one element to another and has this structure:
var f: integer;
S13Be.MXTSTO.data(1,1) := 22;
S12Be.MXTSTO.data(1,S12Be.NFLOW) := 22;
S11Be.MXTSTO.data(1,1) := S12Be.MXTSTO.data(1,S12Be.NFLOW);
S10Be.MXTSTO.data(1,S10Be.NFLOW) := 22;
S9Be.MXTSTO.data(1,1) := S10Be.MXTSTO.data(1,S10Be.NFLOW);
S8Be.MXTSTO.data(1,S8Be.NFLOW) := 22;
S7Be.MXTSTO.data(1,1) := S8Be.MXTSTO.data(1,S8Be.NFLOW);
S5Be.MXTSTO.data(1,S5Be.NFLOW) := 22;
S4Be.MXTSTO.data(1,1) := S5Be.MXTSTO.data(1,S4Be.NFLOW);
S2Be.MXTSTO.data(1,S2Be.NFLOW) := 22;
S1Be.MXTSTO.data(1,1) := S2Be.MXTSTO.data(1,S4Be.NFLOW);
for f := 1 to S13Be.NFLOW+1 do begin
S13Be.MXTSTO.data(1,f) := S13Be.MXTSTO.data(1,1);
end;
for f := 1 to S12Be.NFLOW+1 do begin
S12Be.MXTSTO.data(1,f) := S12Be.MXTSTO.data(1,1);
end;
for f := 1 to S11Be.NFLOW+1 do begin
S11Be.MXTSTO.data(1,f) := S11Be.MXTSTO.data(1,1);
end;
.
.
.
for f := 1 to S2Be.NFLOW+1 do begin
S2Be.MXTSTO.data(1,f) := S2Be.MXTSTO.data(1,1);
end;
for f := 1 to S1Be.NFLOW+1 do begin
S1Be.MXTSTO.data(1,f) := S1Be.MXTSTO.data(1,1);
end;
I would like to put another loop around the outside so that the elements are automatically selected.
The names of the elements are S1Be, S2Be.... S13Be and S1Ent, S2Ent, S3Ent...S13Ent
.MXSTO.data accesses a matrix in the respective element
(1,f) defines the position in the matrix (currently there are only 1x5 and 1x10 matrices; the value .NFLOW specifies which matrix is involved.)
I would be very grateful for a tip, a book recommendation and of course a code.
With best regards
Felix
Translated with www.DeepL.com/Translator (free version)
Names generally no meaning in a compiled program, it doesn't contain them.
If the identifiers are the same type you might be able to define an array of pointers to them, and then iterate using that array.
This can be handled with an enumerated type. The solution will require a little reorganization of your date, but I think it will be worth it. Like most languages variables are independent of each other. If you want to deal with a list of variables they will need to be in a structure of some sort. An array in your case makes sense. However, associating a numeric index with each variable is a bother and requires pointers or some difficult to maintain parsing system.
Nicklaus Wirth created a mechanism to deal with this sort of problem. It is called an enumerated type. For example:
type
BeName = (S1Be, S2Be, S3Be, S4Be);
var
NFLOW: array[BeName] of integer;
MXTSTOdata: array[BeName,1:5,1:10] of integer;
SnBe: BeName;
begin
… Initialization here, the following is how to change your code.
MXTSTOdata(S2Be,1,NFLOW[S2Be]) := 22;
MXTSTOdata(S1Be,1,1) :=MXTSTOdata(S2Be,1,NFLOW[S4Be]);
… Here is just one for loop:
for f := 1 to NFLOW[S1Be]+1 do
MXTSTOdata[S1Be,1,f] := MXTSTOdata[S1Be,1,1];
… Here is a loop of for loops:
for SnBe := S1Be to S4Be do
for f := 1 to NFLOW[SnBe]+1 do
MXTSTOdata[SnBe,1,f] := MXTSTOdata[SnBe,1,1];
Note how the for loop doesn’t need a start and end index. But that depends on which Pascal you are using. Delphi, FreePascal, and standard Pascal differ. You might have to use the first and last element like I showed. You might have a Low and High function available.
var
NFLOW: array[BeName] of integer;
SnBe: BeName;
for SnBe := Low(BeName) to High(BeName) do
for f := 1 to NFLOW[SnBe]+1 do
MXTSTOdata[SnBe,1,f] := MXTSTOdata[SnBe,1,1];
And I might have the syntax for the array declaration wrong. I’ve seen var NFLOW: array of [BeName] of integer; documented on the web, built I haven’t fired up my pascal compiler to check this fragment. However, the enumeration type would help you a lot. Also, there is a for-in construct in FreePascal
for SnBe in BeName do
for f := 1 to NFLOW[SnBe]+1 do
MXTSTOdata[SnBe,1,f] := MXTSTOdata[SnBe,1,1];
The enumeration type is useful in preventing bothersome minor spelling errors from messing up the program, has nice for loop options, and can change the ordering of the values in the enumeration. Changing the ordering may be needed for handling what order assignments are made in, at the cost of program fragility, as you might imagine.
The pred and succ operators are implemented. If you ever wondered what the need were for pred and succ you have now found out. A while loop:
SnBe := S1Be;
repeat
… something
SnBe := succ(SnBe)
until SnBe = S4Be;
Of course that doesn’t get easily to the last value in the enumeration. You could add guard values, but that adds some confusion and messes up the for-in loop.
SnBe := S1Be;
repeat
SomefunctionF(SnBe);
SnBe := succ(SnBe)
until SnBe = S4Be;
SomefunctionF(S4Be);
Is probably the cleanest way to deal with the problem of running in a repeat loop. The reason for adding these examples is you may have two enumerations running in parallel:
type
ToBeName = (S1Be, S2Be, S3Be, S4Be);
NotToBeName = (Bob, Carol, Ted, Alice);
var
NFLOW: array[BeName] of integer;
MXTSTOdata: array[BeName,1:5,1:10] of integer;
Romeo: NotToBeName;
SnBe: BeName;
begin
SnBe:=S1Be;
Romeo:=Bob;
Repeat
ActionFunction(SnBe,Romeo);
SnBe := succ(SnBe);
Romeo := succ(Romeo)
until SnBe = Alice;
Also, this idea might be helpful for your program:
type
EType = (S1Be, S2Be, S3Be, S4Be, Bob, Carol, Ted, Alice);
var
Romeo: EType;
SnBe: EType;
begin
Romeo:= Bob;
SnBe:=S1Be;
repeat
SomeFn(Romeo,SnBe);
SnBe:=succ(SnBe);
until SnBe>S4Be;
The range check applies to pred and succ. For example, the statement
succ(Alice)
would produce an error because there is no element after Alice in the enumerations above.
Lastly, if you need to do things in reverse order you can do:
for SnBe := S4Be downto S1Be do

convert a set to expression Maple/ Change prefix to In-fix expression

How to convert the below set to expression
Expression := {{a°b}, {a°x°y}} # ° can be any operator
required output as
result := {a°b, a°x°y} #required output
I have tried to convert using convert function like below,
asString := convert(Expression, string);
with(StringTools):
asString :=Remove("{}", asString)
result := InertForm:-Parse(asString);
but my output is in the order of Pre-fix expression.
result := {"°(a,b), °(°(a,x),y)"}
Kind regards
restart;
foo := {{a/b}, {a+x*y}}:
result := map(op, foo):
lprint(result);
{a/b, x*y+a}
There is no guarantee that the resulting set will have its entries appearing in the same order as the original set of sets. And hence using sets for this general kind of thing is never going to work properly.
That's why I used nested lists instead of nested sets, in my answers to another of your many questions on this theme last week. Your current Question indicates that you're not following my advice.

Generic to integer conversion in Eiffel

I have some codes like follow:
keys: LINKED_LIST[K]
...
test
local
tempK:K
tempI:INTEGER
do
...
across
keys as cursor
loop
tempK := cursor.item
if tempK ~ 1 then
tempI := tempK
end
end
...
end
"cursor.item" is type of "K". However, the real value inside there is integer type.
thus, "if tempK ~ 1 then" works fine. But "tempI := tempK" doesn't work.
How can I convert tempK's K type to integer? so that it can compile?
In this particular case, where you know that tempK is 1, tempI := 1 will do.
If the idea is to initialize tempI as soon the values stored in the list are of type INTEGER, there are several ways. One is to use an object test:
if attached {INTEGER} tempK as i then
tempI := i
end
However, in this case the test is performed for every element, i.e. inefficient. Changing the code to test for the list type before the loop will help:
if attached {LINKED_LIST [INTEGER]} keys as integer_keys then
...
across
integer_keys as cursor
loop
tempI := cursor.item
end
...
end
If the only operation in the loop is the assignment, the equivalent code is to take just the last element of the list:
...
if not keys.is_empty and then attached {LINKED_LIST [INTEGER]} keys as integer_keys then
tempI := integer_keys.last
end
...
Instead of specialization, the code could also be generalized to take a generic agent that will be passed the key, and the client will supply the procedure to handle the key. But this might be too much, depending on what is the purpose of the task you are solving.

Plotting multiple arrays in maple

I'm trying to plot 4 data-sets in a single coordinate-system. I can plot every single one of them by themselves. However when I try to plot 2 or more with the same plot function I get an error. I can't use lists since I want to scale the arrays up to 2*10000, which a list can't. I'm using Maple 18.
Can anybody please help me solve this?
This is my code:
Here is a plotted data-set:
Here is the error I get, when trying to plot multiple sets(note I have tried using {} instead of []):
Your problem is that your use of pair and zip is not going to produce Arrays P[i] whose layout is valid for plotting. (Perhaps you cribbed that bit of code from something which was intended to produce a list of lists instead of an Array.)
Instead, you could construct the P[i] as iterator-by-2 Matrices (ie. 2-column Matrices).
One way:
restart;
mu := 2.5:
iterator := 25:
fcn := proc(a)
local F,i;
F := Array(1..iterator);
F[1] := a;
for i from 2 by 1 to iterator do
F[i] := mu*F[i-1]*(1-F[i-1]);
end do;
F;
end proc:
f[1]:=fcn(0.01):
f[2]:=fcn(0.1):
f[3]:=fcn(0.3):
f[4]:=fcn(0.5):
x := Array([seq(i,i=1..iterator)]):
for i from 1 to 4 do
P[i] := <x,f[i]>^%T:
end do:
plot([P[1],P[2],P[3],P[4]]);
Another (similar) way:
restart;
mu := 2.5:
iterator := 25:
fcn := proc(a)
local F,i;
F := Vector(1..iterator);
F[1] := a;
for i from 2 by 1 to iterator do
F[i] := mu*F[i-1]*(1-F[i-1]);
end do;
F;
end proc:
f[1]:=fcn(0.01):
f[2]:=fcn(0.1):
f[3]:=fcn(0.3):
f[4]:=fcn(0.5):
x := Vector([seq(i,i=1..iterator)]):
for i from 1 to 4 do
P[i] := <x|f[i]>:
end do:
plot([P[1],P[2],P[3],P[4]]);
You could alternatively use the command plots:-listplot directly on your f[i], though you'd likely way to also specify different colors for each so that it looked nice when you used plots:-display to render them all together.
I leave aside considerations of performance. There are ways to do all this and get faster computation. I deliberately keep your basic methodology.

How to use 'Last attribute on multidimensional arrays in Ada?

I am trying to use the 'Last attribute with a 2D array in Ada, but I can't seem to find the correct syntax to do so.
I know that if I have a 1D array/vector I can use A'last or A'last(n) where n is the nth dimension. But if I do the following
type UnconstrainedArray_2D is array (Integer range <>, Integer range <>) of Integer;
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
for i in 0..tempTable'last(1) loop
for j in 0..tempTable'last(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
end temp;
I get the following compile time error:
Storage_Error stack overflow (or erroneous memory access)
So what am I doing wrong?
I am using GNAT Pro 6.4.1 on Linux.
I'd be very surprised if you got a compile-time Storage_Error on that code.
I've grabbed a copy of your code and modified it as follows; it compiles without error using GNAT (gcc-4.4):
procedure Array_2D is
type UnconstrainedArray_2D is array (Integer range <>, Integer range <>) of Integer;
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
for i in 0..tempTable'last(1) loop
for j in 0..tempTable'last(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
return 42; -- added this
end temp;
begin
null;
end Array_2D;
(Note that I had to add the missing return statement in temp.)
Your syntax for the 'Last attribute (not "command") is correct, but since Ada arrays can have arbitrary lower and upper bounds, it's better to use the 'Range attribute instead:
for i in tempTable'Range(1) loop
for j in tempTable'Range(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
As for the Storage_Error exception, that could easily happen at run time (not compile time) if you call your temp function with a very large value for tempIn. Remember that it has to allocate enough space to hold tempIn**2 Integer objects. Presumably you've also created another UnconstrainedArray_2D object to be passed in as the Table parameter.
It's conceivable that the compiler itself could die with a Storage_Error exception, but I don't see anything in your code that might cause that.
Show us a complete (but small) program that demonstrates the problem you're having, along with the exact (copy-and-pasted) error message. Please distinguish clearly between compile-time and run-time errors.
Your tempTable might have a range of 0..tempIn, but you don't know what range your Table has.. They could be of different length, too.
You would have to check that the length is the same and then use relative indices, like this:
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
if tempTable'Length (1) /= Table'Length (1) or else
tempTable'Length (2) /= Table'Length (2)
then
raise Constraint_Error; -- or something else
end if;
for i in 0 .. tempTable'Length (1) - 1 loop
for j in 0 .. tempTable'Length (2) - 1 loop
tempTable(tempTable'First (1) + i, tempTable'First (2) + j) :=
Table(Table'First (1) + i, Table'First (2) + j);
end loop;
end loop;
end temp;
that way it is ensured that both tables are same length and all indices are valid.
If your tempTable is allowed to be smaller than Table, simply adjust the length check to >. The indices would still be valid.
I don't see an actual value for tempIn set. If the value for tempIn coming into the function temp has not been properly initialized or explicitly set, then the value in tempIn could be anything and probably not something you would like.
I was thinking of a default value. (probably shouldn't post when I am not feeling well :-)

Resources