Can functions like sin () be overridden in Fortran, C, or Java?

Is it possible to override a math function, such as sin() , in Fortran, C, or Java code, while preserving the default behavior of other math functions, such as cos() ? Or can another function be defined called sin() , but which takes different types of arguments in addition to the built-in sin() ? I am interested in the general features of these languages ​​(I mean applications, such as the implementation of non-standard number algebras).

I tried to define the sin() function in Fortran 95, but instead, the internal sin() function was called ... Is there a way around this? how about c and java?

PS : Here is an example application: you already have a calculation code; you understand that it would be useful if all calculations could give numbers with uncertainties (for example, 3.14 Β± 0.01). It would be convenient to store all mathematical expressions (for example, z = sin(x+2*y) ) without changes in the code, even if x and y are numbers with uncertainties (instead of float). This is an example of why the sin() function, which generalizes the normal sinusoidal function, is useful.

The reason I also included in the question the condition that some functions have not been changed is because a user library that calculates the uncertainty on sin(x) when x has uncertainty may not fulfill all standard functions, so it would be It’s nice to have access to some standard features.

These functions are present in Python, and this makes using the uncertainties of the Python module (which I wrote) quite convenient. I would be interested to know how much this convenience is due to the fact that Python is a language, and how convenient is a similar library of uncertainty calculation written for C, Fortran or Java.

+4
source share
6 answers

No problem redefining the built in Fortran. This will not affect other features, but, of course, you will not have access to the intrigue that you are "obscured." Code example:

 module my_subs contains function sin (x) real :: sin real, intent (in) :: x sin = x**2 return end function sin end module my_subs program test_sin use my_subs implicit none write (*, *) sin (2.0) stop end program test_sin 

Exit - 4.0

gfortran gives a warning: "sin" declared in (1) may obscure the internal name with the same name. In order to call internal, explicit INTRINSIC declarations may be required. "Ifort does not give a warning ..

+7
source

In C, you can use a preprocessor:

 #define sin mysin 

Then when you do

 sin(x); 

you are actually calling

 mysin(x); 

You can also get around #include where the sin function is defined, and then you can define your own.

In Java, I believe that it’s enough to write your own implementation in your own package and use it either by importing your package or to define a call:

 mypackage.MyClass.sin(x); 
+5
source

In C, if you do not include <math.h> , then sin is available as a symbol for use by the program - as a function or something else that you like. If you enable it, sin even reserved as a macro, although in practice you will probably find that defining it to call your own function will work.

There are no free functions in Java, so there is no sin function. java.lang.Math.sin(double) is part of the standard libraries, and therefore java.lang.StrictMath.sin(double) . It is not possible to add a method to an existing class, so you cannot replace it. But you can give any other class that you write with a method called sin .

I don't know Fortran at all.

The usual way of working (without any details, what is your actual problem with standard implementations in these languages): call your function something else.

In all languages, your implementation can provide a way to link part or all of the standard libraries to the user version (hell, you can define the whole implementation as a whole if you want to do this job). This will probably be the way to go if you want to reimplement sin . In C, you must compile the library for the link and specify the linker options to use it: libm very similar to any other library. But you should keep in mind that the compiler is allowed, if it chooses, to handle sin specifically for programs with #include d <math.h> . The compiler is allowed to implement any standard function if it is similar to it, so calling sin does not guarantee communication with the sin library function, instead it can use the built-in compiler. If the processor has a sin statement, you might even think that it is a very good idea to avoid calling the function.

In Java, you could in some cases specify a class loader to supply your version of the class, but I'm not sure if this will work with classes in java.lang , since this is a magic namespace. You can always navigate inside your implementation (for example, JRE) and remember (1) that the sin implementation can (should?) Be implemented using your own methods; (2) you can easily break something.

As a rule, there are no guarantees as to whether standard functions refer to each other or not, and if they do, then there are no guarantees whether they will call the standard version or yours. In practice, I think it is unlikely that another standard function will call sin - there is probably an internal auxiliary function called both sin and cos (after taking the module and applying the phase angle), and tan will not use any of them, because that tan(x) = sin(x) / cos(x) not as accurate or fast as you can do in other ways.

+2
source

You cannot replace Math.sin(double) , but you can do MyMath.sin(double) , which you can use instead.

 import static mypackage.MyMath.sin; import static java.lang.Math.cos; // later double s = sin(d); // uses MyMath. double c = cos(d); // uses Math. 
+2
source

You might want to consider a language that is better suited to the task.
As indicated in previous answers, you can avoid using the built-in sin function, but it does not override. For some non-standard numerical algebra (such as a church digital system ), you might consider using a dynamic language such as LISP or Scheme .

+1
source

In C, redefining a function associated with another compilation unit between hard-to-reach ones. It all comes down to the following: when a program is compiled, each imported or exported symbol is listed in the symbol table. You can look at this table using GPL systems, so Linux objdump -T $EXECUTABLE_OR_BINARYOBJECT , on Unix and Linux nm $EXECUTABLE_OR_BINARYOBJECT

The linker then uses this table to identify the parts that will be glued together. First, he reads in the symbol table of each binary and library library provided, fills the symbol table where to look for them, and then associates them with empty symbol import slots (I strongly recommend that every programmer read the linker source code, or better yet, write it - he is very training).

The standard library or libm specifically provides the sin symbol, among other things. Now imagine a program in which the compilation part also exports a symbol named sin . The linker only has symbol names to work with; if a collision occurs, what happens is highly dependent on the linker, but what you can be sure of is that this is unlikely to be desirable.

C ++ prevents namespace conflicts by changing characters. The changed name contains information about the type and namespace. However, if in a C ++ program two characters with the same name and type, without or inside the same namespace, are defined in several compilation units, the same problem exists.

Fortran is even older than C. Like C, there are no namespaces, and again only character names are used for binding. So the problem is the same, at least for Fortran77.

Objective-C is technically C with a message-based object system on top; the same binding rules. Objective-C ++ refers to Objective-C, since C ++ does C.

In Java, every character exists in this class and is thus surrounded by a namespace. Since classes are tied to compilation units, this also prevents namespace conflicts, of course. But it also makes it impossible to redefine things in Java in a straightforward way (although crazy things can be done at the bytecode level).

In Python, external functions are accessed by modules. If you write import spamneggs , then what actually happens is that the special function __import__ is called, and the result is stored as a variable with the name of the modules. The type of this variable is module , but technically it's just a reference to an illustrious dictionary similar to classes. If you write

 import math origsin = math.sin() def mysin(v): return origsin(v) math.sin = mysin 

it happens that you take a copy of the original math.sin and overwrite math.sin with your override. Since instances of modules are shared by the interpreter, unless the sandbox is used, this overrides sin transparent, unremovable way for the entire program. This allows you to choose: either override for the entire program, or use the sandbox to save local data.

I am not such an experienced ruby ​​encoder, so I can not tell you about it.

In Lisp and Scheme, you can do much cooler things than just overriding, but everything you do has only local effects without side effects. In Haskell, this is similar.

+1
source

Source: https://habr.com/ru/post/1381091/


All Articles