Recent

Author Topic: Refference to Sin  (Read 3642 times)

milen_prg

  • Newbie
  • Posts: 2
Refference to Sin
« on: November 25, 2024, 07:14:39 pm »
I want to use variable to call Dynamically selected function (Sin or Cos from the System), but:

Code: Pascal  [Select][+][-]
  1. Program project1;
  2.  
  3. {$R *.res}
  4.  
  5. type
  6.     TFun = function(x: Double): Double;
  7.  
  8. var
  9.     MyFun: TFun;
  10.  
  11. Begin
  12.     MyFun := @Sin;
  13.     WriteLn(MyFun(3));
  14.     ReadLn;
  15. End.
  16.          

project1.lpr(12,14) Error: Incompatible types: got "<address of function(Double):Double;InternProc>" expected "<procedure variable type of function(Double):Double;Register>"

Is this possible in Pascal et all?!

dseligo

  • Hero Member
  • *****
  • Posts: 1455
Re: Refference to Sin
« Reply #1 on: November 25, 2024, 07:53:58 pm »
Sin and cos are intrinsic functions.
Look at this thread i.e.: https://forum.lazarus.freepascal.org/index.php?topic=46204.0

If you use 'normal' functions, then this (based on your example) works:
Code: Pascal  [Select][+][-]
  1. Program project1;
  2.  
  3. uses math;
  4.  
  5. type
  6.   TFun = function(x: Double): Double;
  7.  
  8. var
  9.   MyFun: TFun;
  10.  
  11. Begin
  12.   MyFun := @ArcSin;
  13.   WriteLn(MyFun(3));
  14.   ReadLn;
  15. End.

WooBean

  • Sr. Member
  • ****
  • Posts: 279
Re: Refference to Sin
« Reply #2 on: November 25, 2024, 07:58:05 pm »
A bit efforts needed:

Code: Pascal  [Select][+][-]
  1. Program project1;
  2.  
  3. {$R *.res}
  4.  
  5. type
  6.   TFun = function(x: Double): Double;
  7.  
  8. function sin(x:double): double;
  9. begin
  10.   result:=system.Sin(x);
  11. end;
  12.  
  13. var
  14.     MyFun: TFun;
  15.  
  16. Begin
  17.     MyFun := @Sin;
  18.     WriteLn(MyFun(3));
  19.     ReadLn;
  20. End.
  21.  

Platforms: Win7/64, Linux Mint Ulyssa/64

Warfley

  • Hero Member
  • *****
  • Posts: 1856
Re: Refference to Sin
« Reply #3 on: November 25, 2024, 07:58:32 pm »
Sin, Cos and so on are not Pascal language functions, they are just references to FPU instructions. So see them rather than an Assembly macro than an actual function

MarkMLl

  • Hero Member
  • *****
  • Posts: 8138
Re: Refference to Sin
« Reply #4 on: November 25, 2024, 08:10:19 pm »
A bit efforts needed:

Code: Pascal  [Select][+][-]
  1. ...
  2. type
  3.   TFun = function(x: Double): Double;
  4.  
  5. function sin(x:double): double;
  6. ...
  7.  

I wonder whether to compiler would deign to inline those...

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Warfley

  • Hero Member
  • *****
  • Posts: 1856
Re: Refference to Sin
« Reply #5 on: November 25, 2024, 08:23:57 pm »
Theres actually a feature that I would like to build one day, to be able to get the reference of internals by the compiler generating such helper functions by itself. Most notably to be able to turn operators into function pointer. Because I had so often to do the following for like a sorting algorithm:
Code: Pascal  [Select][+][-]
  1. function MyLess(x, y: MyType): Boolean;
  2. begin
  3.   Result := x<y;
  4. end;
  5.  
  6. SortArray(array, @MyLess);
Just to be usable as a comparison operator. If I could instead just write:
Code: Pascal  [Select][+][-]
  1. SortArray(array, @operator<)
Or something would make it so much easier

MarkMLl

  • Hero Member
  • *****
  • Posts: 8138
Re: Refference to Sin
« Reply #6 on: November 25, 2024, 08:31:55 pm »
Yes, that makes a great deal of sense. However my brain begins to hurt a little at this point since /if/ parameter preparation for a machine operation (like Sin... there's an opcode for that) follows normal conventions then there seems to be no reason why a pointer to it can't be constructed, while if it does not follow normal conventions run-time dereferencing of a pointer to a function would appear to equate to self-modifying code.

I'm not sure I've explained that very well...

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MathMan

  • Sr. Member
  • ****
  • Posts: 405
Re: Refference to Sin
« Reply #7 on: November 25, 2024, 11:49:35 pm »
Sin, Cos and so on are not Pascal language functions, they are just references to FPU instructions. So see them rather than an Assembly macro than an actual function

That is a very short description of the topic. 'Sin', 'Cos' and other are only available as FPU instructions on x8087 - and even there they are range limited. So range reduction must be applied etc. Though short this still translates to several lines of asm under a compilerproc function name - something like fpc_sin_... (too tired to look up the exact).

If you don't have x8087 available, like all embedded, ARM, etc. then you'll find an actual Pascal implementation with series approximation. This is quite old >20 years if I have it correct. It is mapped to the same internal function name as above and the elementary operations like +,- and * of these may even be mapped to soft-float emulation if the target architecture does not provide hardware for that.

Quite convoluted setup, but unfortunately neccessary to address the plethora of target architectures.

milen_prg

  • Newbie
  • Posts: 2
Re: Refference to Sin
« Reply #8 on: November 26, 2024, 09:32:17 am »
Thank, you! Now I understand. BUT:
In Pascal so many technical/system things are without normal logic, can't be understand by beginner, because usually are atavist part of ancient technologies. (For example, it is very mysterious for me even this that Sin is not defined with Double, but with some strange alias ValReal. Such things with types are so many in Pascal at all. In this sense I came from C and there everything is simple, clear and logical, unfortunately C has fatal problems with graphics...).

It would be extremely useful this Notice to be in the standard Documentation of FPC about the Sin, Cos, etc.
Thankfully, you are great community!

Thaddy

  • Hero Member
  • *****
  • Posts: 16421
  • Censorship about opinions does not belong here.
Re: Refference to Sin
« Reply #9 on: November 26, 2024, 11:29:10 am »
https://www.freepascal.org/docs-html/rtl/math/sincos.html
Note on Intel, AMD and possibly ARM this is much faster than calling either sin or cos separately.
So a separate function like yours is not necessary in most cases.
Also note sin, cos and sincos are indeed dependent on processor register width, so differ between 32 and 64 bit in precision and I believe that is documented. It is about handling the FPU part, so on i386 it can be 80 bit.
« Last Edit: November 26, 2024, 11:34:32 am by Thaddy »
There is nothing wrong with being blunt. At a minimum it is also honest.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8138
Re: Refference to Sin
« Reply #10 on: November 26, 2024, 11:44:40 am »
Nice reminder Thaddy, but I don't see how that answers the question without using local variables to store the result and then reading one or the other... which departs a long way from OP's intention.

What would be somewhat more useful is something like APL's circle operator, which takes a parameter to specify which transcendental is to be applied.

https://aplwiki.com/wiki/Circular#Examples

The point here is that both the right and left operands could be arrays, so the operation applied to each element might be different (Sin to some, Cos to others and so on).

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 5823
  • Compiler Developer
Re: Refference to Sin
« Reply #11 on: November 28, 2024, 09:06:20 pm »
A bit efforts needed:

Code: Pascal  [Select][+][-]
  1. ...
  2. type
  3.   TFun = function(x: Double): Double;
  4.  
  5. function sin(x:double): double;
  6. ...
  7.  

I wonder whether to compiler would deign to inline those...

The compiler does not inline function/method pointers. In theory there might be situations where it might be possible, but currently these are not handled.

VisualLab

  • Hero Member
  • *****
  • Posts: 620
Re: Refference to Sin
« Reply #12 on: November 28, 2024, 11:13:00 pm »
Thank, you! Now I understand. BUT:
In Pascal so many technical/system things are without normal logic, can't be understand by beginner, because usually are atavist part of ancient technologies. (For example, it is very mysterious for me even this that Sin is not defined with Double, but with some strange alias ValReal.

Click on the ValReal link provided in the Sin function documentation and you will see that it takes you to a page explaining what ValReal is :) It is simply an alias to Extended. here's an description (explanation) at the bottom of this page:

Quote
ValReal is an alias for the largest available floating point type on the architecture the program runs on. On most processors, it should be one of Double or Extended.

Such things with types are so many in Pascal at all. In this sense I came from C and there everything is simple, clear and logical, unfortunately C has fatal problems with graphics...).

There are many such things in different (and many) programming languages. Pascal is no exception in this respect. And no, C is not simpler. And it has fatal problems not only with graphics :D On the contrary, it is much more confusing and messy. You've simply become accustomed to the shortcomings, quirks, and difficulties that the C has over the years of using it. Every programmer feels this way after years of using languages.

It would be extremely useful this Notice to be in the standard Documentation of FPC about the Sin, Cos, etc.
Thankfully, you are great community!

Yes, you're right, it definitely should be like that. It would be nice if the maintainer of the web pages describing such functions would add the information that Warfley, MathMan and Thaddy have provided.
« Last Edit: November 28, 2024, 11:17:06 pm by VisualLab »

MarkMLl

  • Hero Member
  • *****
  • Posts: 8138
Re: Refference to Sin
« Reply #13 on: November 29, 2024, 08:48:44 am »
Yes, you're right, it definitely should be like that. It would be nice if the maintainer of the web pages describing such functions would add the information that Warfley, MathMan and Thaddy have provided.

In that case raise a feature request against the documentation. Stuff that's merely discussed here will be overlooked.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

LV

  • Full Member
  • ***
  • Posts: 198
Re: Refference to Sin
« Reply #14 on: November 29, 2024, 03:59:09 pm »
The compiler does not inline function/method pointers. In theory there might be situations where it might be possible, but currently these are not handled.

Interesting, let's try it.

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. uses
  4.   SysUtils;
  5.  
  6. type
  7.   TFun = function(x: double): double;
  8. var
  9.   MyFun: TFun;
  10.   i, j, t1, t2, t3: QWord;
  11.   y: double;
  12.  
  13.  function sin_(x: double): double; inline;
  14.   begin
  15.     Result := sin(x);
  16.   end;
  17.  
  18. begin
  19.   MyFun := @sin_;
  20.  
  21.   Write('direct call |');
  22.   write(' inline call|');
  23.   writeln(' pointer call|');
  24.  
  25.   for j := 1 to 5 do
  26.   begin
  27.     // direct call
  28.     t1 := GetTickCount64;
  29.     for i := 1 to 10000000 do
  30.     begin
  31.       y := sin(i);
  32.     end;
  33.     Write(GetTickCount64 - t1, '           ');
  34.     // inline call
  35.     t2 := GetTickCount64;
  36.     for i := 1 to 10000000 do
  37.     begin
  38.       y := sin_(i);
  39.     end;
  40.     write(GetTickCount64 - t2, '          ');
  41.     // pointer call
  42.     t3 := GetTickCount64;
  43.     for i := 1 to 10000000 do
  44.     begin
  45.       y := MyFun(i);
  46.     end;
  47.     writeln(GetTickCount64 - t3);
  48.  
  49.   end;
  50.  
  51.   readln;
  52.  
  53. end.
  54.  

Output:

Code: Text  [Select][+][-]
  1. direct call | inline call| pointer call|
  2. 312           313          312
  3. 297           313          297
  4. 297           281          297
  5. 297           296          297
  6. 282           297          281
  7.  

 

TinyPortal © 2005-2018