I am encountering a problem when manipulating sequence element in Maple. First of all, here is the code.
b[0] := t -> (1-t)^3;
b[1] := t -> 3*t*(1-t)^2;
b[2] := t -> 3*t^2*(1-t);
b[3] := t -> t^3;
P := seq([seq([j*(i+1), j*(i-1)], i = 1 .. 4)], j = 1 .. 3);
EvalGamma := proc (b, P, i, t)
local CP, res;
option trace;
CP := P[i];
res := CP[1]*b[0](t)+CP[2]*b[1](t)+CP[3]*b[2](t)+CP[4]*b[3](t);
RETURN res;
end proc;
The variable P is a sequence of sequence : P[i] is a sequence of four 2D points.
But the affectation CP := P[i]; doesn't do what I want : I don't know why but the result is not P[i] in the procedure.
And the weird thing is that, outside the procedure, the following lines work :
CP := P[1];
CP[1];
I would appreciate any suggestions. Thanks.
I'm assuming you call the procedure as
EvalGamma(b,P,i,t)
The problem you are having is that when P is inserted into the sequence of arguments, the nested sequence of arguments is "flattened" to produce the final argument list. An easy way to fix this is to place the sequence for P inside a list structure. So use
P := [seq([seq([j*(i+1), j*(i-1)], i = 1 .. 4)], j = 1 .. 3)];
Once you do that, I think everything will work as expected.
When you call EvalGamma you cannot pass that global P which is an expression sequence of (three) lists (or lists). If you try and do so then EvalGamma will receive 6 arguments instead of 4 as you intend, because each of the three lists (of lists) in expression sequence P gets interpreted as a separate argument of the call.
Instead, you could create P as a list, ie,
P := [seq([seq([j*(i+1), j*(i-1)], i = 1 .. 4)], j = 1 .. 3)];
or you could pass it like EavlGamma(b, [P], some_i, some_name). But you should only do one of those two choices.
Note that the return syntax should be either return res; or (deprecated) RETURN(res);.
Related
I want to make subprogram for adding array's elements with Ada.
subprogram "Add_Data" have 3 parameters-
first parameter = generic type array (array of INTEGER or array of REAL)
second parameter = INTEGER (size of array)
third parameter = generic type sum (array of INTEGER -> sum will be INTEGER, array of REAL -> sum will be REAL)
I programmed it from ideone.com.
(I want to see just result by array of INTEGER. After that, I will test by array of REAL)
With Ada.Text_IO; Use Ada.Text_IO;
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
procedure test is
generic
type T is private;
type Tarr is array (INTEGER range <>) of T;
--function "+" (A,B : T) return T;
--function "+" (A, B : T) return T is
--begin
-- return (A+B);
--end "+";
procedure Add_Data(X : in Tarr; Y : in INTEGER; Z : in out T);
procedure Add_Data(X : in Tarr; Y : in INTEGER; Z : in out T) is
temp : T;
count : INTEGER;
begin
count := 1;
loop
temp :=temp+ X(count); //<-This is problem.
count := count + 1;
if count > Y then
exit;
end if;
end loop;
Z:=temp;
end Add_Data;
type intArray is array (INTEGER range <>) of INTEGER;
intArr : intArray := (1=>2, 2=>10, 3=>20, 4=>30, 5=>8);
sum : INTEGER;
procedure intAdd is new Add_Data(Tarr=>intArray, T=>INTEGER);
begin
sum := 0;
intAdd(intArr, 5, sum);
put (sum);
end test;
when I don't overload operator "+", It makes error.
"There is no applicable operator "+" for private type "T" defined."
What can I do for this?
If a generic’s formal type is private, then nothing in the generic can assume anything about the type except that it can be assigned (:=) and that it can be compared for equality (=) and inequality (/=). In particular, no other operators (e.g. +) are available in the generic unless you provide them.
The way to do that is
generic
type T is private;
with function "+" (L, R : T) return T is <>;
This tells the compiler that (a) there is a function "+" which takes two T’s and returns a T; and (b) if the actual T has an operator "+" which matches that profile, to allow it as the default.
So, you could say
procedure intAdd is new Add_Data (T => Integer, ...
or, if you didn’t feel like using the default,
procedure intAdd is new Add_Data (T => Integer, "+" => "+", ...
In addition to not knowing how to declare a generic formal subprogram (Wright has shown how to do this for functions), your code has a number of other issues that, if addressed, might help you move from someone who thinks in another language and translates it into Ada into someone who actually uses Ada. Presuming that you want to become such a person, I will point some of these out.
You declare your array types using Integer range <>. It's more common in Ada to use Positive range <>, because people usually refer to positions starting from 1: 1st, 2nd, 3rd, ...
Generics are used for code reuse, and in real life, such code is often used by people other than the original author. It is good practice not to make unstated assumptions about the values clients will pass to your operations. You assume that, for Y > 0, for all I in 1 .. Y => I in X'range and for Y < 1, 1 in X'range. While this is true for the values you use, it's unlikely to be true for all uses of the procedure. For example, when an array is used as a sequence, as it is here, the indices are immaterial, so it's more natural to write your array aggreate as (2, 10, 20, 30, 8). If I do that, Intarr'First = Integer'First and Intarr'Last = Integer'First + 4, both of which are negative. Attempting to index this with 1 will raise Constraint_Error.
Y is declared as Integer, which means that zero and negative values are acceptable. What does it mean to pass -12 to Y? Ada's subtypes help here; if you declare Y as Positive, trying to pass non-positive values to it will fail.
Z is declared mode in out, but the input value is not referenced. This would be better as mode out.
Y is not needed. Ada has real arrays; they carry their bounds around with them as X'First, X'Last, and X'Length. Trying to index an array outside its bounds is an error (no buffer overflow vulnerabilities are possible). The usual way to iterate over an array is with the 'range attribute:
for I in X'range loop
This ensures that I is always a valid index into X.
Temp is not initialized, so it will normally be initialized to "stack junk". You should expect to get different results for different calls with the same inputs.
Instead of
if count > Y then
exit;
end if;
it's more usual to write exit when Count > Y;
Since your procedure produces a single, scalar output, it would be more natural for it to be a function:
generic -- Sum
type T is private;
Zero : T;
type T_List is array (Positive range <>) of T;
with function "+" (Left : T; Right : T) return T is <>;
function Sum (X : T_List) return T;
function Sum (X : T_List) return T is
Result : T := Zero;
begin -- Sum
Add_All : for I in X'range loop
Result := Result + X (I);
end loop Add_All;
return Result;
end Sum;
HTH
I keep receiving error,';' unexpected in this piece of maple code. I have looked and looked and just can't seem to find where I'm going wrong. Can anyone spot it?
QSFactorization := proc (n::(And(posint, odd)), mult::nonnegint := 0, { mindeps::posint := 5, c := 1.5 })
local mfb, m, x, fb, nfb, r, M, d;
if isprime(n) then
return "(n)"
elif issqr(n) then
return "(isqrt(n))"*"(isqrt(n))"
elif n < 1000000 then
return ifactor(n)
end if;
if mult = 0 then
mfb := MultSelect(n, ':-c' = c)
else mfb := [mult, FactorBase(mult*n, c)]
end if;
m := mfb[1];
if 1 < m then
print('Using*multiplier; -1');
print(m)
end if;
x := m*n*print('Using*smoothness*bound; -1');
print(ceil(evalf(c*sqrt(exp(sqrt(ln(n)*ln(ln(n))))))));
fb := Array(mfb[2], datatype = integer[4]);
nfb := ArrayNumElems(fb);
print('Size*of*factor*base; -1');
print(nfb);
r := Relations(x, fb, ':-mindeps' = mindeps);
M := r[3]; print('Smooth*values*found; -1');
print(nfb+mindeps);
print('Solving*a*matrix*of*size; -1');
print(LinearAlgebra:-Dimension(M));
d := Dependencies(M);
print('Number*of*linear*dependencies*found; -1');
print(nops(d));
print('Factors; -1');
FindFactors(n, r, d)
end proc
I'd really appreciate any insight.
You basic problem is that you are using the wrong quotes inside your print statements. This is invalid,
print('Using*multiplier; -1');
You are using single right-quotes (tick), which in Maple is used for unevaluation. In this case the semicolons inside your print statements are syntax errors.
Use either double-quotes or single left-quotes instead. The former delimits a string, and the latter delimits a name. Eg,
print("Using*multiplier; -1");
print(`Using*multiplier; -1`);
If you choose to go with name-quotes then the print command will prettyprint the output in the Maple GUI with the name in an italic font by default, but you won't see the quotes in the output.
If you choose to go with string-quotes then the print command will show the quotes in the output, but will use an upright roman font by default.
Some other comments/answers (since deleted) on your post suggest that you are missing statement terminators (colon or semicolon) for these two statements,
print(m)
FindFactors(n, r, d)
That is not true. Those statements appear right before end if and end proc respectively, and as such statement terminators are optional for them. Personally I dislike coding Maple with such optional terminator instances left out, as it can lead to confusion when you add intermediate lines or pass the code to someone else, etc.
A friend of mine posed an interesting question to me today about how to write immediately invoked named functions in CoffeeScript without hoisting the function variable to the outer scope.
In JavaScript:
(function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); })(5);
The best I could come up with in CoffeeScript:
do -> do factorial = (n = 5) ->
if n <= 1 then 1 else n * factorial(n-1)
looks a bit awkward. Is there a better way to do this?
You can’t. CoffeeScript doesn’t support this kind of thing at all, except via inline JavaScript:
result = `(function factorial(n) {`
return if n <= 1 then 1 else n * factorial(n-1)
`})(5)`
(No indenting allowed, either.) CoffeeScript will insert some semicolons for you, too, so no using it in expression context.
Then again…
-> if n <= 1 then 1 else n * arguments.callee n-1
(don’t do that)
The exact question would be "is the equation you want to use x=f(Xo)". This is in an if statement already so if true then continue if not then prompt user to enter a different function.
Your bit about its already being inside an if statement isn't very workable because that doesn't allow for an alternative value to be assigned to something in the case that the initial response is negative.
You should be able to work with something like this. Call p(), and assign its result to a ans, say, and then work with that value (and/or test it for some properties).
restart:
p := proc()
local answer, oldprompt, res1, res2;
oldprompt := interface(':-prompt'=``);
try
printf("Is the equation you want to use x=f(Xo)? (y/n)\n");
res1 := readline(-1);
if member(res1,{"y;","y","yes;","yes"}) then
answer := x=f(Xo);
elif member(res1,{"n;","n","no;","no"}) then
printf("Enter your equation.\n");
res2 := readline(-1);
answer := parse(res2);
else
printf("Response not recognized\n");
end if;
catch:
finally
interface(':-prompt'=oldprompt);
end try;
if answer='answer' then NULL else answer end if;
end proc:
ans := p();
[edited below]
It is possible to get it a little closer to your original. With procedure p as below the returned result will be one of true/false/FAIL and could be used in a conditional. In the case that the return values if false (because of the response to the initial query) then a second query is made about the choice of another expression.
This version of p takes two arguments, the first is the suggested initial equation. The second is a name which can be assigned any alternative.
restart:
p := proc(candidate, resultvar)
local result, oldprompt, res1, res2;
oldprompt := interface(':-prompt'=``);
try
printf(sprintf("Is the equation you want to use %a? (y/n)\n",
candidate));
res1 := readline(-1);
if member(res1,{"y;","y","yes;","yes"}) then
result := true;
assign(resultvar,candidate);
elif member(res1,{"n;","n","no;","no"}) then
result := false;
printf("Enter your equation.\n");
res2 := readline(-1);
assign(resultvar,parse(res2));
else
printf("Response not recognized\n");
result := FAIL;
end if;
catch:
finally
interface(':-prompt'=oldprompt);
end try;
return result;
end proc:
Now we can test it out.
p(x=f(X0), 'ans');
ans;
We could also use the call to p inside an if statement. Eg,
if p(x=f(X0), 'ans') then
"accepted";
else
"new choice made";
end if;
ans;
Here, answering "n" to the first query will make the conditional test see a false value, but the named argument ans will get assigned to as a side-effect.
I have the following auto hotkey script:
A:= 5
B := "7"
C := A.B
MsgBox %C%
The third line does not work.
I'm expecting output of "57"
I have tried the following:
C := %A%.%B%
C := (A).(B)
C := (A.B)
C := (%A%.%B%)
C := (%A%).(%B%)
None of which work
Can anyone tell me how to do it?
I'm using version 1.1.09.04
Just updated to latest version 1.1.14.01 and its still the same
You have distinguish between expressions (:=) and "normal" value assigments (=). Your goal can be met with several approaches, as shown in the following examples:
a := 5
b := 7
x := 6789
; String concatenation
str1 = %a%%b%
; or as an expression
str2 := a b
; or with explicit concatenation operators
str3 := a . b
; Mathematical "concatenation"
; if b has exactly one digit
val1 := a*10 + b
; for any integer
val2 := a * (10**StrLen(x)) + x ; ** is the "power" operator
msgbox, str1 = %str1%`nstr2 = %str2%`nstr3 = %str3%`nval1 = %val1%`nval2 = %val2%
This code will print:
str1 = 57
str2 = 57
str3 = 57
val1 = 57
val2 = 56789
In AHK, all of these methods should be quasi-equivalent: They produce the same kind of output. The mathematical approach marks the variables as numbers, leading to possible trailing zeros, which you may want to Round() before displaying. The output of our string concatenation can be used as a number as well, since AHK auto-boxes them if neccessary. For example, you could calculate
z := str1 - 1
and it would evaluate to 56.
I personally prefer the mathematical approach, since it will result result in an actual number and not a string, which seems only logical.