Same block of code in a SELECT TYPE in Fortran - fortran

I’m wondering if there is an elegant way to avoid repeating block of code that apply to different types in a SELECT TYPE construct. Consider for example:
select type (var)
type is (t1_t)
codeA (many lines of code)
type is (t2_t)
codeA (same lines)
...
type is (tn_t)
codeB
class default
codeC
end select

Unlike the select case construct, where you can group multiple tests in the same case satement, there is no such facility in the select type construct.
The reason is: within the block of each type-guard statement, the selector (variable or expression you're matching) will have the same type as named in the type-guard statement, and won't be polymorphic there. This is how you can have dynamic type resolution in Fortran, that is statically typed.
select type (var)
type is (t1_t)
! Here, type of var is t1_t, and you can call
! procedures that use type(t1_t) as arguments with var
type is (t2_t)
! Here, type of var is t2_t, and procedures expecting
! type(t1_t) as arguments won't work with var
...
end select
Therefore, compiler can't allow you to group many types in the same type-guard, because it would't know which dynamic type to apply on the selector.
As a side note, unlike switch satement in c-derived languages, select constructs in Fortran do not fall through, i.e., after a match in Fortran, the corresponding block is executed and the control exits the construct.
As #cup said, you can convert whatever you have in common on the various branches in a subroutine in order to avoid repetition. But be aware that if you need to pass var to the routine, you must declare it as polymorphic dummy.

As francescalus pointed out in the comments, the typical way to repeat the same lines of code is to use an include file. This is a traditional technique which used to be widely used for common blocks and is also used for poor-man's templating.
included.f90:
codeA (many lines of code)
main.f90:
select type (var)
type is (t1_t)
include "included.f90"
type is (t2_t)
include "included.f90"
...
end select
If you use the C preprocessor, you can use the preprocesor's #include as well.

There is the overloaded operator type of construct that the 'type is' suggests. That needs to be in a module as a subroutine or function. I mostly use functions, so if one is mixing with C, then subroutines may be easier than a function trying to return a vector.
It will still be the same exact code, just operating on a complex, float, double, or variety of integer but depths... so there is no explicit 'type of' as the right version is selected based upon the arguement types.

Related

AnyLogic - dynamic schedule for resourcePool cast from Integer to TimeUnits

I refer to the following SOW post and the answer of Stuart Rossiter.
I thought it was right to open a new thread about this, as the problem can be looked at a little differently after all these years. Now I get the following error: "The method create_ShiftChange(double, TimeUnits) in the Main type is not applicable for the arguments (int, Integer)."
As I noted in my comment from Stuart Rossiter's solution, I believe the function create_ShiftChange(...) had different input arguments a few years ago.
The cast from getTimeoutToNextValue() to double is not a problem. However, the cast of the second argument getNextValue() from Integer to TimeUnits presents me with a challenge.
Does anyone have a solution for my problem or do I have to look for a detour, since the "old" create_ShiftChange(...) also has a different meaning due to the other input arguments? Thanks for the help!
There hasn't been a change in the create_* functions (methods) for dynamic events. There are two forms:
One where you explicitly specify the time units for when it should be scheduled (so with 2 initial arguments of type double and TimeUnits). TimeUnits is a Java enum (effectively what an AnyLogic option list is under the covers) with values like TimeUnits.MINUTE; auto-complete will show you the alternatives.
One where you implicitly assume the time units of the model as a whole, as in its properties (so with 1 initial argument of type double).
The dynamic event in question has a single int argument (i.e., its 'event-specific' data comprises just an integer), so the relevant create_* function variants have this as their final argument (i.e., they have 3 and 2 arguments respectively).
In your case, you are not using a dynamic event with a single argument (otherwise the method create_ShiftChange(double, TimeUnits) it's complaining about wouldn't exist — it would be create_ShiftChange(double, TimeUnits, int) instead) and, since you've called it with two integers, the compiler (incorrectly) assumes you were trying to use the 2 argument form, hence the error message.
So either add the argument to the dynamic event or, if in your case you're using a different set of arguments (or no arguments) for your dynamic event, change accordingly.
You simply need to type TimeUnits. (note the dot!) and then use code-complete. This shows you all the options you have available, choose the one you need.
Background: This is an enum defined by AnyLogic to be used for time units. When you see things like that, always type it out and try code-complete

How are quantities referenced in Fortran?

I was told a long time ago that in FORTRAN, everything is passed by value. Therefore I would need to do this (provided mySubroutine is suitably defined elsewhere):
double precision :: myArray(2)
myArray(1:2) = (/ 2.3d0, 1.5d0 /)
CALL mySubroutine(myArray)
However, I also found that the program compiles and runs as expected if I do this
CALL mySubroutine((/ 2.3d0, 1.5d0 /))
without needing to define an intermediary array myArray. I thought that I was passing myArray into mySubroutine by reference. What is going on under the hood in the second version? Is the compiler unpacking the subroutine call, declaring a temporary variable only to pass it by reference?
To a large extent, trying to classify Fortran procedure calling with pass-by-reference and pass-by-value is not too helpful. You can find more detail on that in response to questions like this one and this one.
In short, generally procedure references are such that changes to a variable in a procedure are reflected in the variable where the procedure was referenced. In some cases a compiler may choose to do copy-in/copy-out, and in others it effectively must. Equally, the value attribute of a dummy argument specifies that an anonymous copy be made.
Where this question adds something a little different is in the use of an expression such as in
call mySubroutine([2.3d0, 1.5d0]) ! Using F2003 array constructor syntax
Is the compiler creating a temporary variable?
Admittedly, this is perhaps just a looseness in terminology but it's worth saying that there is certainly no variable involved. [2.3d0, 1.5d0] is an expression, not a variable. Crucially this means that it cannot be modified (appear in a variable definition context) in the procedure. Restrictions that apply in the case using an expression rather than a (temporary) variable include:
the dummy argument associated with an expression may not have the intent(inout) or the intent(out) attribute;
if the dummy argument hasn't an intent attribute then that argument may not be modified if the associated actual argument is an expression.
Now, if the dummy argument has the value attribute the effect of the procedure is the same whichever way it is referenced.
To conclude, the program may work just as well with an expression instead of an intermediate variable. If it doesn't that's because of violation of some aspect of Fortran. How it works is a problem for the compiler not the programmer.

typed vs untyped vs expr vs stmt in templates and macros

I've been lately using templates and macros, but i have to say i have barely found information about these important types. This is my superficial understanding:
typed/expr is something that must exists previously, but you can use .immediate. to overcome them.
untyped/stmt is something that doesn't to be defined previously/one or more statements.
This is a very vague notion of the types. I'd like to have a better explanation of them, including which types should be used as return.
The goal of these different parameter types is to give you several increasing levels of precision in specifying what the compiler should accept as a parameter to the macro.
Let's imagine a hypothetical macro that can solve mathematical equations. It will be used like this:
solve(x + 10 = 25) # figures out that the correct value for x is 15
Here, the macro just cares about the structure of the supplied AST tree. It doesn't require that the same tree is a valid expression in the current scope (i.e. that x is defined and so on). The macro just takes advantage of the Nim parser that already can decode most of the mathematical equations to turn them into easier to handle AST trees. That's what untyped parameters are for. They don't get semantically checked and you get the raw AST.
On the next step in the precision ladder are the typed parameters. They allow us to write a generic kind of macro that will accept any expression, as long as it has a proper meaning in the current scope (i.e. its type can be determined). Besides catching errors earlier, this also has the advantage that we can now work with the type of the expression within the macro body (using the macros.getType proc).
We can get even more precise by requiring an expression of a specific type (either a concrete type or a type class/concept). The macro will now be able to participate in overload resolution like a regular proc. It's important to understand that the macro will still receive an AST tree, as it will accept both expressions that can be evaluated at compile-time and expressions that can only be evaluated at run-time.
Finally, we can require that the macro receives a value of specific type that is supplied at compile-time. The macro can work with this value to parametrise the code generation. This is realm of the static parameters. Within the body of the macro, they are no longer AST trees, but rather ordinary well typed values.
So far, we've only talked about expressions, but Nim's macros also accept and produce blocks and this is the second axis, which we can control. expr generally means a single expression, while stmt denotes a list of expressions (historically, its name comes from StatementList, which existed as a separate concept before expressions and statements were unified in Nim).
The distinction is most easily illustrated with the return types of templates. Consider the newException template from the system module:
template newException*(exceptn: typedesc, message: string): expr =
## creates an exception object of type ``exceptn`` and sets its ``msg`` field
## to `message`. Returns the new exception object.
var
e: ref exceptn
new(e)
e.msg = message
e
Even thought it takes several steps to construct an exception, by specifying expr as the return type of the template, we tell the compiler that only that last expression will be considered as the return value of the template. The rest of the statements will be inlined, but cleverly hidden from the calling code.
As another example, let's define a special assignment operator that can emulate the semantics of C/C++, allowing assignments within if statements:
template `:=` (a: untyped, b: typed): bool =
var a = b
a != nil
if f := open("foo"):
...
Specifying a concrete type has the same semantics as using expr. If we had used the default stmt return type instead, the compiler wouldn't have allowed us to pass a "list of expressions", because the if statement obviously expects a single expression.
.immediate. is a legacy from a long-gone past, when templates and macros didn't participate in overload resolution. When we first made them aware of the type system, plenty of code needed the current untyped parameters, but it was too hard to refactor the compiler to introduce them from the start and instead we added the .immediate. pragma as a way to force the backward-compatible behaviour for the whole macro/template.
With typed/untyped, you have a more granular control over the individual parameters of the macro and the .immediate. pragma will be gradually phased out and deprecated.

Overloading Present for multiple arguments

Is it possible to overload Present(arg) so I can have
Present(arg1,arg2,...) to mean
If (Present (arg1) .And. Present (arg2) .And. ... )
I am trying to do it but it feels as though it is not so straightforward to do.
Interestingly the answer is: no, you cannot. You can indeed create a generic identifier called present and have a new specific name:
module mod
interface present
module procedure present_two_real
end interface
contains
logical function present_real_real(a,b)
..
end function
end module
However, inside that function we know that the dummy arguments must be optional. If they weren't it wouldn't be legal to pass optional actual arguments in a procedure to that function: see Fortran 2008 12.5.2.12.
When we look at how we different two procedures must be to be able to have the same generic identifier (12.4.3.4.5) we have constraint C1215. It's this constraint with the optional requirement in the new specific name which makes us unable to do what you want. Note that the argument in the specific procedure present isn't optional.
That doesn't mean you can't have a generic present_all, of course. You'll need a specific procedure for each combination of argument characteristics you want, though (as my choice of specific name above suggests). [Recall that template's are not in Fortran's style.] Further, you'll still need to handle the requirement to distinguish the specific implementations. It all sounds like a bit too much work, really.

Conversion of multiple internal types to system level types

At my workplace, I am working on a use case where I have to convert multiple internal/product level data types to C++ compatible data types. Earlier we used something called as switch fence where code would look like
switch(InternalTypeCategory)
{
case InternalTypeA:
convert_to_int8_t;
break;
case InternalTypeB:
convert_to_int16_t
break;
.....
}
But for the sake of performance and other related issues, we are going to convert this switch fence block to C++ template based code where we dont have use switch case every now and then.
What have I tried so far?
I have been playing around with boost::any, boost::variant and boost::any_cast, boost::numeric_cast but nothing concrete has come up so far. I always end up with repetition of code or use some sort of mechanism (control structures or hash table) to select the particular value to have enough information for type conversion.
The internal/product level data types are variants (in terms of size, signed/unsigned) of integer, floating point, double and character.
Kindly help. Thanks in advance.
Templates only help you if the type is defined at compile-time. Since you're using a variant, I assume that this is not possible.
However a simple approach is to use a table of conversion methods and then use the internalType as index for these methods.
Create a generic interface for all conversion functions:
typedef InternalVariant (*conversionFunc_ptr)(const InternalVariant& data);
define an array of all available functions and assign as necessary:
static conversionFunc_ptr conversionFunc[MaxInternalTypeCategory];
conversionFunc[InternalTypeA] = convert_to_int8;
conversionFunc[InternalTypeB] = convert_to_int16;
[...]
And in the actual function use it like this:
return conversionFunc[InternalTypeCategory](*this);
Note: You shouldn't use instance members but static members. So you need to supply the variable to the function (otherwise you need to have the conversion array for each value instead only once)