Skip to content

TFormula: Possibility of failure during dynamic compilation of predefined functions "gausn" and "landau" #17225

Open
@AlexeyVKrasnoperov

Description

@AlexeyVKrasnoperov

Check duplicate issues.

  • Checked for duplicates

Description

It may happen that the program has a locale with a comma as a decimal separator
("fr_FR.utf8", "de_DE.utf8", "ru_RU.utf8", .. ).
In this case, initialization of the TFormula objects with functions "gausn" and "landau"
ends with an error. The following messages are displayed on the screen:
...
input_line_11:2:158: error: too many arguments to function call, expected single argument 'x', have 2 arguments
Double_t TFormula____id3053186198674332598(Double_t *x,Double_t *p){ return p[0]*TMath::Exp(-0.5*(((x[0])-p[1])/p[2])*(((x[0])-p[1])/p[2]))/(TMath::Sqrt(2*3,141593)*p[2]) ; }
...

input_line_13:2:115: error: too many arguments to function call, expected at most 4, have 5
Double_t TFormula____id3986067622224738083(Double_t *x,Double_t *p){ return p[0]*TMath::Landau((x[0]),p[1],p[2],0,000000) ; }
...

Reproducer

It is enough to execute this macro in ROOT with different locale names as a parameter.

#include <TFormula.h>
#include <locale.h>

void CheckTFormula(const char *locale = nullptr)
{  
  if( locale != nullptr )
    {
      const char * ptr = setlocale(LC_NUMERIC,locale);
      if( ptr == nullptr )
        {
          fprintf(stderr,"Cannot set locale: \"%s\"\n",locale);
          return;
        }
      printf("Numeric locale: \"%s\"\n",ptr);
    }
  lconv * lc = localeconv();
  if( lc != nullptr )
    printf("Decimal point: \"%s\"\n",lc->decimal_point);
  //
  double num = 12345.67890;
  printf("printf: \"%lf\"\n",num);  
  printf("TString::Format: \"%s\"\n\n",TString::Format("%lf",num).Data());
  //
  TFormula f0("f0","gausn(x)");
  if( f0.IsValid() )
    {
      f0.Print();
      printf("\n");
    }
  //
  TFormula f1("f1","landau(x)");
  if( f1.IsValid() )
    f1.Print();
}

ROOT version

ROOT 6.32.08. Perhaps everywhere, starting from new TFromula ?

Installation method

build from source

Operating system

Linux, Debian 12.8

Additional context

To prevent the appearance of additional arguments and set the correct constants,
it is enough to forcibly replace the comma with a dot when converting floating-point numbers to strings.

In file: root/hist/hist/src/TFormula.cxx
https://github.com/root-project/root/blob/2c8521e17d40134df0e6194b993387fcade96d97/hist/hist/src/TFormula.cxx#L2266
The code on the line 2266
TString value = TString::Format("%lf", (*constIt).second);
need to be replaced with
TString value = TString::Format("%lf", (*constIt).second).ReplaceAll(",",".");

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions