I'm trying to implement the extended euclidean algorithm given in pseudo-code below, in KornShell (ksh).
I am having problems with the lines with ":=" - I don't know what those mean.
I'm also having problems with the multiple return variables.
How can I implement this?
function extended_gcd(a, b)
x := 0 lastx := 1
y := 1 lasty := 0
while b ≠ 0
quotient := a div b
(a, b) := (b, a mod b)
(x, lastx) := (lastx - quotient*x, x)
(y, lasty) := (lasty - quotient*y, y)
return (lastx, lasty)
:= part :
:= is not for shell scripting , for assignments we use simple "=" in scripts ie
var="abcd" ;
:= is available in other tools though , like in make -- where it stands for immediate assignment.
what immediate assignment means is that the variable gets assigned a value the moment its parsed.
there are also other variants available like =? ... etc.
fxn return value part :
its a basic rule that a function can return only a single value.
But iff you are intrested in being able to use multiple variables outside the function body then -- bash/korn/shell in general dont have any specific concept as a local variable .
by default what ever variables you have in a script are global ie available throughout .... but within the scope of the current shell only .
you would need to export the variables to make them available in a child shell.
syntax : export variable_name ;
Also you need to use {} braces to define a function body. ie
fxn_name()
{
var=$1; ## if you want to use a variable
......
....
}
its invokation/call is
fxn_name $arg ;
Related
I am trying to see how to test short circuit evaluation in Pascal but not sure if doing it correctly. This is what I have so far.
program shortcircuit;
var
{ local variable definition }
a : integer;
b : integer;
begin
a := 8;
b := 0;
if( (b <> 0) and (a / b) ) then
(* if condition is true then print the following *)
writeln('...' )
end.
It is unclear what your question is, but you should try to provide a program that actually compiles before posting. This will help you answer your own questions.
The first problem you have is that Pascal has no concept of automatically convert to boolean that many C-derived languages do. You must test the inequity with zero explicitly.
I would also add an else clause to print when your test works successfully.
var
{ local variable definition }
a : integer;
b : integer;
begin
a := 8;
b := 0;
if( (b <> 0) and ((a / b) <> 0.0) ) then
(* if condition is true then print the following *)
writeln('fooey' )
else writeln('short circuited')
end.
http://tpcg.io/_HUNS7P
It is possible, should you make some minor modifications to the LHS of the and expression, that the compiler will notice you are hard-coding an attempt to divide by zero and complain.
Finally, Pascal always does short-circuit evaluation by default. You can disable it with a compiler directive, but that is always The Wrong Thing To Do.
For your example (avoiding a divide by zero error), the code will do the correct thing by default.
if (b <> 0) and some_predicate_function( a / b ) then ...
Though if you are just doing a checked divide, you could just make yourself a useful function that defaults to an acceptable value:
function checked_divide( a,b:integer; fooey:double = 0.0 ) : double;
begin
if b <> 0
then result := a / b
else result := fooey
end;
The notion of short-circuit evaluation is not part of the language:
Boolean expressions have the property that their value may be known before the entire expression has been evaluated.
Assume for example, that X = 0.
Then the value of the expression
(x > 0) and (X < 10)
is already known to be false after computation of the first factor, and the second need not be evaluated.
Whether or not the second factor is evaluated is implementation-dependent.
This means that you must assure that the second factor is well defined, independent of the value of the first factor.
[…]
Source:
Jensen, Kathleen; Wirth, Niklaus.
Pascal – user manual and report (4th revised ed.).
p. 32.
doi:10.1007/978‑1‑4612‑4450‑9.
ISBN 978‑0‑387‑97649‑5.
Therefore, you need to consult your compiler’s documentation.
Delphi and the FreePascal Compiler have the {$B+}/{$boolEval on} and {$B‑}/{$boolEval off} (default) compiler directives, disabling and enabling short-circuit evaluation respectively.
The GNU Pascal Compiler recognizes {$B+}/{$B‑} too, plus {$short‑circuit}/{$no‑short‑circuit}.
However, the default is not to guarantee either, I don’t know, maybe for some SIMD optimizations.
Pascal “likes” writing things out.
Because, or if this implementation-dependence is dissatisfying or unwanted, the ISO standard 10206 “Extended Pascal” introduces two other Boolean operators:
A primary, a factor, a term, or a simple‑expression shall be designated an operand.
Except for the and_then and or_else operators, the order of evaluation of the operands of a dyadic operator shall be implementation-dependent.
NOTE —
This means, for example, that the operands may be evaluated in textual order, or in reverse order, or in parallel, or they may not both be evaluated.
6.8.3.3 Boolean operators
[…]
In a term of the form A and_then B, the right operand shall be evaluated if and only if the left operand denotes the value true;
the term shall denote the value false if the left operand denotes the value false;
otherwise, the term shall denote the value denoted by the right operand.
In a simple‑expression of the form A or_else B, the right operand shall be evaluated if and only if the left operand denotes the values false;
the simple-expression shall denote the value true if the left operand denotes the value true;
otherwise, the simple-expression denotes the value denoted by the right operand.
Unfortunately, of the previously mentioned compilers only the GNU Pascal Compiler supports and_then/or_else.
Generally speaking, if you want “short-circuit evaluation”, you have to write it out in Pascal (e. g. a nested if in lieu of and_then).
Experimentally determining your compiler’s behavior.
I am trying to see how to test short circuit evaluation in Pascal but not sure if doing it correctly.
A test design would use Boolean functions with side-effects, particularly writeLns, like so:
program shortCircuitTest(output);
function A: Boolean;
begin
writeLn('A');
A := false;
end;
function B: Boolean;
begin
writeLn('B');
B := true;
end;
{ === MAIN ========= }
begin
if A and B then
begin
writeLn('then branch');
end
else
begin
writeLn('else branch');
end;
end.
However, this is only an indicator.
You really need to consult your compiler’s documentation to know the details.
What is the correct way to convert an always changing integer variable to a string (to be displayed on a VGA monitor)? I have a series of if statements that take care of padding (so that the resulting string is always a certain length but as soon as I change:
resulting_string <= integer'image(87465);
to:
resulting_string <= integer'image(some_int_var);
I get an "Expression is not constant" error. What is the correct way to convert an always changing integer variable (that could be any int within the integer limits) to a string?
edit: not duplicate of the other question
'image (..) does not work on signals.
I think you are still missing the main problem: A monitor can not display strings or chars!
You need to implement
1. a graphic buffer,
2. a buffer reader that outputs VGA data.
Then you need to implement a manipulator to
draw shapes
clear the screen
move areas and
copy pictures into the buffer.
The glyphs are stored in a ROM and are choosen by a BCD value for each digit.
Converting an integer to a 'string' does not need a ASCII string, because the result is a BCD code (not ASCII). So you need to implement an (un)signed to BCD converter, too.
I went at it from every direction and finally found that I had to make a giant case block to get it to work. Now I can finally display rapidly changing variables that are really helpful for debugging. It's unfortunate that the solution had to be so retarded though..
(I already have a ROM for displaying text that the resulting string is sent to.)
function int_to_str(int : integer) return string is
variable a : natural := 0;
variable r : string(1 to 11);
begin
a := abs (int);
case a is
when 0 => r := "0 ";
when 1 => r := "1 ";
when 2 => r := "2 ";
when 3 => r := "3 ";
.
.
.
when 1000 => r := "1000 ";
when others => r := "???????????";
end case;
if (int < 0) then
r := '-' & r(1 to 10);
end if;
return r;
end int_to_str;
The following code, taken from Gnu Pascal test code, will compile nicely in Free Pascal. And I can understand how it works.
var s1 : set of 0..255;
s2 : set of 64..128;
ok : boolean;
procedure p1;
begin
if s1 = s2 then begin
writeln('failed1');
ok := false;
end;
end;
However, I'm slightly curious what the rules are for set compatibility and what you can expect. For example:
program p;
var
a : set of 0..10;
b : set of 20..100;
s : integer;
begin
b := [20];
a := [];
if a = b then
writeln('a')
else
writeln('b');
end.
This prints 'b'. But if I have two empty sets (b := [];) then they are considered equal.
I'm just trying to get my head around how this actually gets implemented.
(What I'm kind of thinking is that the two sets are converted to the union of the ranges, so set of 0..100 are created, and two temporaries from a and b as set of 0..100, and then comparison is done those temporaries).
Sets with integers as base type (the type after the set of) are always compatible.
Your assumption is correct: in general both sets are converted to temporaries with common ranges and then the temporaries are compared. The conversion is done by calls to fpc_varset_load.
If you are interested in more details, the code which decides how to convert the sets, is located in nadd.pas (see 1) starting at line 1593.
The problem
I'm writing a function in a package which converts some values for a testbench. I want to check the if the output exceeds a maximum value, if it does I want to set it to that maximum value. What I tired was the following:
-- vec_in: 0...1023, returns -14...23.5 dB
function conv_dac602_scale (
vec_in : std_logic_vector)
return real is
variable val_in, dB : real := 0.0;
constant lower : real := -14.0;
constant upper : real := 23.5;
begin -- function conv_dac602_scale
val_in := real(to_integer(unsigned(vec_in)));
dB := (lower+(val_in*((upper-lower)/1024.0)));
return dB when dB <= upper else upper; -- this is the important line! (129)
end function conv_dac602_scale;
When I try to compile this I got the following errors:
** Error: myfile.vhd(129): near "when": expecting ';'
** Error: myfile.vhd(260): VHDL Compiler exiting
I then tried assigning it to a variable r first:
...
r := dB when dB <= upper else upper; -- this is the important line! (129)
return r;
end function conv_dac602_scale;
Which did not change the outcome. I know that I can use a simple if/else clause instead, but my question is why I can't use the when clause.
System
Modelsim SE 10.0b, VHDL 2008
The target <= signal when x is a so called concurrent statement, which is designed for easy creation of signal assignments outside a process. You can use it within an architecture, but not inside a process. If and else are designed for sequential statements within a process. In your case, you'll have to use if/else.
Edit:
Seems this only holds true for Vhdl pre 2008. As fru1tbat pointet out, this is valid vhdl 2008 code and the problem is a not supported feature by the Modelsim compiler.
I would reconsider changing the way you call your return, as it looks like your syntax using WHEN is incorrect.
Clarify what you're trying to do with:
return dB when dB <= upper else upper;
That essentially is "return dB when dB is less than or equal to upper, else upper" where upper will not be returned due to the way you make the return statement. You may want to say: ... else return upper
I would prefer an if statement in this case:
if ( dB <= upper) then
return dB;
else
return upper;
end if;
I have a feature
feature --compare
is_less alias "<" (other: MONEY): BOOLEAN
-- Is current money less than `other'?
local
temp: BOOLEAN
do
temp := cents < other.cents
Result := temp
end
It just checks two number of cents (cents < other.cents) is greater than.
I cannot get the Result to return true even if i set it too true:
Result := temp -----> Result := true
I am using 13.11 and it works well for me.
is_less alias "<" (other: like Current): BOOLEAN
require
not_void: other /= Void
do
Result := cents < other.cents
end
In another class I call this function and it works as expected.
do_compare
local
m1, m2: MONEY
do
create m1.make_from_volume (1)
create m2.make_from_volume (2)
print(m1.is_less (m2))
end
So I wonder how did not check if the Result is True or not? How did you pass the argument to it?