For loop is ambiguous - loops

I'm using Visual Basic 2008EE and I have a problem with this loop:
If x = CType("new", Primitive) Then
TextWindow.Write("How many new users would you like to add? ")
k = TextWindow.ReadNumber()
For mt = 1 To k
NewUserEntry()
Next
and i get this error:
"type of 'mt' is ambigious because the loop bounds and the step clause do not convert to the same type"
I appreciate any help.

The return type of ReadNumber (or more accurately, the type of k variable) is probably not an Integer. When the compiler wants to infer the type of the mt, it fails since k, which is specified as the loop bound has one type (probably something like Double) and the loop step (implicitly the integer constant 1) has the type Integer. The compiler will not automatically assume the type of mt since the two don't match.
For mt As Integer = 1 To k
NewUserEntry()
Next

Related

Assign complex array from real arrays in Fortran [duplicate]

I want to assign complex array as variable.
My code is like
complex indx(3,3)
integer i,j
do i=1,3
do j=1,3
indx(i,j) = (i,j)
write(*,*) indx(i,j)
end do
end do
and in this case I am getting an error like
A symbol must be a defined parameter in this context. [I]
indx(i,j) = (i,j)
You must use function cmplx to build a complex value you want to assign.
complex indx(3,3)
integer i,j
do i=1,3
do j=1,3
indx(i,j) = cmplx(i,j)
write(*,*) indx(i,j)
end do
end do
The syntax you tried is only valid for constant literals.
The answer by Vladimir F tells the important part: for (i,j) to be a complex literal constant i and j must be constants.1 As stated there, the intrinsic complex function cmplx can be used in more general cases.
For the sake of some variety and providing options, I'll look at other aspects of complex arrays. In the examples which follow I'll ignore the output statement and assume the declarations given.
We have, then, Vladimir F's correction:
do i=1,3
do j=1,3
indx(i,j) = CMPLX(i,j) ! Note that this isn't in array element order
end do
end do
We could note, though, that cmplx is an elemental function:
do i=1,3
indx(i,:) = CMPLX(i,[(j,j=1,3)])
end do
On top of that, we can consider
indx = RESHAPE(CMPLX([((i,i=1,3),j=1,3)],[((j,i=1,3),j=1,3)]),[3,3])
where this time the right-hand side is in array element order for indx.
Well, I certainly won't say that this last (or perhaps even the second) is better than the original loop, but it's an option. In some cases it could be more elegant.
But we've yet other options. If one has compiler support for complex part designators we have an alternative for the first form:
do i=1,3
do j=1,3
indx(i,j)%re = i
indx(i,j)%im = j
end do
end do
This doesn't really give us anything, but note that we can have the complex part of an array:
do i=1,3
indx(i,:)%re = [(i,j=1,3)]
indx(i,:)%im = [(j,j=1,3)]
end do
or
do i=1,3
indx(i,:)%re = i ! Using scalar to array assignment
indx(i,:)%im = [(j,j=1,3)]
end do
And we could go all the way to
indx%re = RESHAPE([((i,i=1,3),j=1,3))],[3,3])
indx%im = RESHAPE([((j,i=1,3),j=1,3))],[3,3])
Again, that's all in the name of variety or for other applications. There's even spread to consider in some of these. But don't hate the person reviewing your code.
1 That's constants not constant expresssions.

Passing parameters to macro with a loop

There is a task to fill deep structure with macro, where names of structure components are similar and can be constructed by simple loop with index.
For example, the structure is root-level1-level2-level3-level4
I wanna fill it with following nested macros
DEFINE iterate_menges.
do &4 times.
fill &1 &2 sy-index level4.
enddo.
END-OF-DEFINITION.
DEFINE fill.
cs_root-sheet&1-&2-level&3-&4 = 'some_value'.
END-OF-DEFINITION.
But this concept doesn't work and sy-index is treated like a text. The error
component cs_root-sheet1-level2-levelsy-index-level4 is not found
is shown, however numeric literal works wonderfully.
What syntax should be used here?
ADDITION: here is an example snippet I found on SCN and it works perfectly. Why is so?
DEFINE ADD_MAPPING.
p_c = &1.
CONDENSE p_c.
CONCATENATE 'p_old' p_c INTO p_c.
ASSIGN (p_c) TO <fs>.
WRITE <fs>.
END-OF-DEFINITION.
DO 14 TIMES.
ADD_MAPPING sy-index.
ENDDO.
P.S. Yes, I know macros are undebuggable, unsafe and totally shouldn't be used, but I am interested in this particular problem and not best-practice advice.
Using dynamic programming, change your fill macro to:
DATA l_field TYPE string.
FIELD-SYMBOLS <l_value> TYPE any.
DEFINE fill.
l_field = &3.
CONDENSE l_field.
CONCATENATE 'cs_root-sheet&1-&2-level' l_field '-&4' INTO l_field.
ASSIGN (l_field) TO <l_value>.
IF sy-subrc = 0.
<l_value> = 'some_value'.
ELSE.
" TODO: error handling?
ENDIF.
END-OF-DEFINITION.
This will work, although you might want to check sy-subrc after the ASSIGN because that parameter is invariant (only known at runtime) and thus will not pick up errors at compile-time like the other parameter would.
You can also add compile-time validation for the upper-bound of your DO loop since you thus know the maximum value of sy-index. To do this, you can add a non-executing reference in the iterate_menges macro:
DEFINE iterate_menges.
IF 1 = 0. " compile-time boundary validation test
cs_root-sheet&1-&2-level&4-level4 = ''.
ENDIF.
DO &4 TIMES.
fill &1 &2 sy-index level4.
ENDDO.
END-OF-DEFINITION.
A second method is to add a case statement. This can only be used if you know there will always be a certain amount of fields in that part (surely there should always be at least one...). So if you know the bottom bound of your DO loop, then you can code the following as a optimization:
CASE &3.
WHEN 1. " set 1
WHEN 2. " set 2
WHEN 3. " set 3
" ...
WHEN OTHERS.
" dynamic set
ENDCASE.
Since the dynamic set is slower, optimizing tight loops is always a good idea.
The system is doing exactly what is stated in the documentation. Unfortunately, in this case, the English translation is lacking some details as opposed to the German original text which is more to the point, IMHO. Usage of a macro is not a call of some sort, it's a textual replacement that happens before compilation. The parameters are replaced, not evaluated - they can not be evaluated because in most cases, the value is not known at compile time, only at runtime. To do what you want to do, you will have to use dynamic access techniques like ASSIGN COMPONENT ... OF ...
What you are trying to do is impossible, because the macros are only known at compilation time. They are no part of means of modularization in ABAP.
One could even write his own version of Brainfuck. Look at the following example.
REPORT zzz.
TYPES: BEGIN OF t1,
sheet1 TYPE c,
sheet2 TYPE c,
END OF t1.
DATA:
cs_root TYPE t1.
DEFINE test.
cs_root-sheet&1 = 'costam'.
END-OF-DEFINITION.
DEFINE brainfuck.
&4=>&1&3 &2.
END-OF-DEFINITION.
START-OF-SELECTION.
brainfuck IF_SYSTEM_UUID_STATIC~CREATE_UUID_X16 ) ( CL_SYSTEM_UUID.
test sy-index.
Answering your comment under the other answer. The solution could look like this.
REPORT zzz.
TYPES: BEGIN OF t4,
level4 TYPE c,
END OF t4.
TYPES: BEGIN OF t3,
level1 TYPE t4,
level2 TYPE t4,
END OF t3.
TYPES: BEGIN OF t2,
level1 TYPE t3,
level2 TYPE t3,
END OF t2.
TYPES: BEGIN OF t1,
sheet1 TYPE t2,
sheet2 TYPE t2,
END OF t1.
CLASS lcl_test DEFINITION FINAL.
PUBLIC SECTION.
CLASS-METHODS:
test
IMPORTING
i_1 TYPE i
i_2 TYPE i
i_3 TYPE i
CHANGING
cs_root TYPE t1.
ENDCLASS.
CLASS lcl_test IMPLEMENTATION.
METHOD test.
ASSIGN COMPONENT |sheet{ i_1 }| OF STRUCTURE cs_root TO FIELD-SYMBOL(<fs_sheet>).
IF sy-subrc = 0.
ASSIGN COMPONENT |level{ i_2 }| OF STRUCTURE <fs_sheet> TO FIELD-SYMBOL(<fs_level1>).
IF sy-subrc = 0.
ASSIGN COMPONENT |level{ i_3 }| OF STRUCTURE <fs_level1> TO FIELD-SYMBOL(<fs_level2>).
IF sy-subrc = 0.
ASSIGN COMPONENT 'level4' OF STRUCTURE <fs_level2> TO FIELD-SYMBOL(<fs_level3>).
IF sy-subrc = 0.
<fs_level3> = 'some_value'.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDMETHOD.
ENDCLASS.
DEFINE test.
lcl_test=>test(
EXPORTING
i_1 = &1
i_2 = &2
i_3 = &3
CHANGING
cs_root = &4
).
END-OF-DEFINITION.
DATA: gs_root TYPE t1.
START-OF-SELECTION.
DO 14 TIMES.
test 1 2 sy-index gs_root.
ENDDO.

How to Pass value as dynamic array from vb to c

I have below declaration:
Type routineStruct
man As String * 3
number As String * 5
End Type
Type vbToC
sch As String * 4
routine(0 To 10000) As routineStruct
End Type
vbfun As vbToC
Now we are sending this vbfun As vbToC from VB to C.
Now for above vbToC type , 64K memory limit error is occuring while compiling.
So, we use the dynamic array as like -
Type vbToC
sch As String * 4
routine() As routineStruct
End Type
And then assign value
Redim routine(10000)
For loop = 0 To 10000
.routine(loop).man = value1
.routine(loop).number = value2
Next
My question is above vbToc declaration for dynamic array is right or not? if right then can it be possible to send values from vb to c with this dynamic array and how to receive the value for dynamic array for each structure element?
In VB6 the type you have defined as "routineStruct" is invalid. You would most certainly receive a compile error here. If you are trying to declare "man" and "number" as arrays the syntax is not correct. You would need to use a declaration similar to your "routine" element with an array declaration.
Furthermore, you have declared your type without any access modifier. When you do this it will default to "private." If you were to export the VB6 ActiveX DLL to a type library for use in C++ the type would therefore not be visible and marshaling would not be possible.
The solution would be to adjust your type declaration to include proper VB6 syntax as well as make the type public. Marshaling of native string types become BSTR in C/C++ and you should have no problem here.

FORTRAN - Assigning an array value to variable

Is there a way to get the value of an array to the shape of a variable? Even when I select a single value of an array, say A(1:1, 1:1), it still complains when I compile and want to assign this to a variable:
Error: Incompatible ranks 0 and 1 in assignment at (1)
The goal in the end is something like this:
H = MAXVAL(matrix) - epsilon
IF ( matrix(i:i, i:i) >= H ) THEN
...
but I cannot make this comparison because H is a variable and matrix(i:i, i:i) a 1x1 array. Is the only possibility for this to work to make H and array, too?
Thank you for your help!
Do not specify a range, use a single element:
A(1,1)=1
Your statement would then read:
H = MAXVAL(matrix) - epsilon
IF ( matrix(i, i) >= H ) THEN
Background:
Fortran allows you to work on sub-arrays like:
A(1:10,2:5)
which would be a 10x4 array. So A(1:1,1:1) is in fact an array (1x1) (as you noted). A(1,1), on the other hand, is a scalar and can be treated as such.

I want to extract values from an array and use them in a string expression

I am trying to do a for loop of a nonlinear fit where one of the coefficients changes values with each iteration. These values are in an array called YoungMod. I have:
for k=1:size(DataAll,3)
ft = fittype('E1*(YoungMod(k))-b*t','coefficients',{'E1','b'},'independent', 't','dependent','depth','options',fo);
[FittedData{k},gof{k}] = fit(DataAll(:,3,k),DataAll(:,1,k),ft1); %{k});
coeffs{k}=coeffvalues(FittedData{k});
end
The error message I receive is:
Error using fittype>iTestCustomModelEvaluation (line 726)
Expression
E1*(YoungMod(k))-b*t
is not a valid MATLAB expression, has non-scalar coefficients, or cannot be evaluated:
Error in fittype expression ==>
(E1*YoungMod(k))-b*t
??? Undefined function 'YoungMod' for input arguments of type 'double'.
To me, it looks like the issue is that the string is reading YoungMod*(k) instead of taking the k value of the YoungMod array. Help is greatly appreciated!
I managed to solve this problem using a dummy variable and the 'problem' option for fittype:
for k=1:size(DataAll,3)
ym = YoungMod(k)
ft = fittype('E1*(ym)-b*t','coefficients',{'E1','b'},'independent', 't','dependent','depth','options',fo,'problem','ym');
[FittedData{k},gof{k}] = fit(DataAll(:,3,k),DataAll(:,1,k),ft,'problem',ym);
coeffs{k}=coeffvalues(FittedData{k});
end
Try this instead to make sure k is evaluated as a variable and not a string:
ft = fittype(['E1*(YoungMod(' num2str(k) '))-b*t'],'coefficients',{'E1','b'},'independent', 't','dependent','depth','options',fo);

Resources