Recent

Author Topic: Log10 in FPC versus Log10 in Delphi question. Also need FPC/DCC Guidelines  (Read 7866 times)

LV

  • Sr. Member
  • ****
  • Posts: 427

In the meantime, just remember that later definitions take precedence in identifier resolution, meaning that you can do this, for instance:

Code: Pascal  [Select][+][-]
  1. implementation
  2.  
  3. uses
  4.   Math;
  5.  
  6. function Log10(X: Double): Double;
  7. begin
  8.   if X <> 0 then Result := Math.Log10(X) else Result := -Infinity;
  9. end;
  10.  
  11. // From here on "Log10" refers to the wrapper function

Simple solution.  Thank you!

The overridden log10 function for a negative argument gives a runtime error. To avoid this

Code: Pascal  [Select][+][-]
  1. program Project1;
  2. uses
  3.   math;
  4.  
  5. function Log10(X: Double): Double;
  6. begin
  7.   if X > 0 then Result := Math.Log10(X)
  8.   else
  9.   if X = 0 then Result := -Infinity
  10.   else Result := NaN;
  11. end;
  12.  
  13. begin
  14.  
  15.   writeln('log10(1) = ', log10(1));  // 0.0000000000000000E+000
  16.   writeln('log10(0) = ', log10(0));  // -Inf
  17.   writeln('log10(-1) = ', log10(-1)); // Nan
  18.  
  19.   Readln;
  20. end.  
  21.  

gues1

  • Guest
Code: Pascal  [Select][+][-]
  1. implementation
  2. uses
  3.   Math;
  4. function Log10(X: Double): Double;
  5. begin
  6.   if X <> 0 then Result := Math.Log10(X) else Result := -Infinity;
  7. end;
  8. // From here on "Log10" refers to the wrapper function
Simple solution.  Thank you!

Really  :o ... missing something ?

Code: Pascal  [Select][+][-]
  1.   a := log10(10);
  2.   writeln(a);
  3.   a := log10(0);
  4.   writeln(a);
  5.   a := log10(-1);
  6.   writeln(a);
  7.  

Quote
1.00000000000000E+0000
                   -Inf
                    Nan

LV

  • Sr. Member
  • ****
  • Posts: 427
Maybe I'm missing something, please tell me

gues1

  • Guest
Maybe I'm missing something, please tell me
Sorry, I write the post in same time like you.

But, why you tell that is sometihing wrong ? The result should be NAN.

I used Delphi to show the results 'cause Delphi works like IEEE 754 said.

LV

  • Sr. Member
  • ****
  • Posts: 427
Maybe I'm missing something, please tell me
Sorry, I write the post in same time like you.

But, why you tell that is sometihing wrong ? The result should be NAN.

I used Delphi to show the results 'cause Delphi works like IEEE 754 said.

Thanks, now it's clear. My results were obtained using FPC 3.2.2.  :)

Schmitty2005

  • Jr. Member
  • **
  • Posts: 65
And to top it off, I did not verify this solution in FPC or Delphi. I liked it because it was a simple approach.  I have not had a chance to try it out. 

Thaddy's solution to fix the exception is the best, but a little over my head.

gues1

  • Guest
And to top it off, I did not verify this solution in FPC or Delphi. I liked it because it was a simple approach.  I have not had a chance to try it out. 

Thaddy's solution to fix the exception is the best, but a little over my head.
You cannot do that for all maths functions, it's a nosense.

And of course the proposal of @Thaddy is the best and the only way.

Paolo

  • Hero Member
  • *****
  • Posts: 738
Quote
I think that, if you would expect always a good result why you don't only check the last result always waiting for the entire "chain" of calculations ?

As I've already explained, I have very long calculations, and if something went wrong at the beginning, why should I wait hours?

Anyway, I'll stop here; obviously, our use cases are very different.

To summarize the orignal topic:

1) there nothing wrong in both delphi and fpc
2) there was a change in the "deafult" settings in the exceptionmask, that is:
    delphi default silently passes inf, nan, etc along the computation
    fpc default throws exceptions
3) both delphi and fpc can behave the same way simply setting the excpetion mask in the same way (see Thaddy answer)
4) two notes are :
  a) be aware of that (Compatibility)
  b) Delphi adheres to latest standard beahviour

So everyone can be happy and set their own preferences.


Schmitty2005

  • Jr. Member
  • **
  • Posts: 65
In Delphi versions prior to Athens the behavior was the same as FPC: exception.
If you want FreePascal to return -inf you can do that like this:
Code: Pascal  [Select][+][-]
  1. {$ifdef fpc}{$mode delphi}{$endif}
  2. uses Math;
  3. var
  4.  x:Double = 0.0;
  5. begin
  6.   SetExceptionMask(GetExceptionMask + [exInvalidOp, exZeroDivide]);
  7.   writeln(Log10(x));  // prints -inf like modern Delphi's
  8. end.
On the other hand, if you want Delphi to throw an exception, you can do that like this:
Code: Pascal  [Select][+][-]
  1. {$ifdef fpc}{$mode delphi}{$endif}
  2. uses Math;
  3. var
  4.  x:Double = 0.0;
  5. begin
  6.   SetExceptionMask(GetExceptionMask - [exInvalidOp, exZeroDivide]);
  7.   writeln(Log10(x));// floating point exception. Like in older Delphi's and FPC
  8. end.
So in principle nothing needs fixing as long as you are aware of the internals.
Also note that Delphi changed its behavior, not Freepascal....

Modern Delphi follows IEEE 754 where log(0) is treated as a domain error and returns -inf instead of throwing an exception.
In that sense modern Delphi's are standards compliant. This is what most compilers do.
But as I have shown, you can make fpc behave the same.
I am not sure it warrants a bug report.

Should this solution at least this be added to the FPC doc for Log10 in the meantime ?

https://www.freepascal.org/docs-html/rtl/math/log10.html

Thaddy

  • Hero Member
  • *****
  • Posts: 19388
  • Glad to be alive.
Because our Delphi friends will solve it in the same way, I might add.
There is a lot of bloat in this discussion, I am glad you, as OP, understood the first answer.
objects are fine constructs. You can even initialize them with constructors.

gues1

  • Guest
Should this solution at least this be added to the FPC doc for Log10 in the meantime ?
https://www.freepascal.org/docs-html/rtl/math/log10.html

Because our Delphi friends will solve it in the same way, I might add.

Cannot be done in this way.

Change the MASKS changes all math operations of the application. YOU MUST restore the masks if you want use it for LOG10 only, or you can use TThread.

A note should be insert if you change the docs about that.

Thaddy

  • Hero Member
  • *****
  • Posts: 19388
  • Glad to be alive.
No. No need to restore: he just wants his code to be delphi compatible, so the mask can stay.
objects are fine constructs. You can even initialize them with constructors.

 

TinyPortal © 2005-2018