3

I am mixing C with C++ source code using GNU. _Decimal64 is recognised fine in C, but not in C++. C++ complains error: '_Decimal64' does not name a type.

Is there any way I can fix this? Should I consider it a compiler bug?

Update 20-Mar-2017 18:19:

None of the answers meet my requirements so far. I don't want to use the decimal64 C++ class, I want to use the _Decimal64 C type. My project is mostly written in C, but I want to slowly introduce C++ code. Here, for example, is part of cell.h:

union vals
  {
          num c_n;
          //double c_d;
          char *c_s;
          long c_l;
          int c_i;
          struct rng c_r;
  };

It is made use of in cells.c, which of course is C code. num is defined in numeric.h:

#pragma once

#ifdef __cplusplus
#define USE_DECIMAL 0
#else
#define USE_DECIMAL 1
#endif

#if USE_DECIMAL
typedef _Decimal64 num;
#define NUM_HUNDREDTH 0.01DL
#define NUM_TEN 10.0DL
#else
typedef double num;
#define NUM_HUNDREDTH 0.01
#define NUM_TEN 10.0
#endif

Notice that I have use typedef double num to get a compile on the C++ side. C++ doesn't actually num type, but it is inevitably included because it needs some of the functionality in the C files.

It's faking it, of course.num isn't a double, it's really a _Decimal64. I'm asking how I can get around this kludge.

phuclv
  • 37,963
  • 15
  • 156
  • 475
blippy
  • 1,490
  • 1
  • 13
  • 22

4 Answers4

1

For C++ "decimal64"

use std::decimal::decimal64

the standard says:

https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-api-4.6/a00454.html

Pavan Chandaka
  • 11,671
  • 5
  • 26
  • 34
  • It's **not** a standard type in C++, still a [TR](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3871.html) – phuclv Jun 05 '22 at 03:25
  • yes, did you look at the [latest C++ standard](https://eel.is/c++draft/)? It's no where to be found. There's [no update to the decimal TR either](https://en.cppreference.com/w/cpp/experimental) so this terrible answer is still entirely incorrect – phuclv Jun 06 '22 at 02:22
  • and this is [straight from the `std::decimal` proprosal's author](https://stackoverflow.com/a/14096071/995714) – phuclv Jun 06 '22 at 02:30
1

_Decimal64 is neither standard C++ nor standard C. It is simply proposed in the TR 24732 document.

Ok, gcc supports it at least when compiling C source. The C++ counterpart seems to be TR 24733. It defines a std::decimal::decimal64 class.

Those definition are likely to be compatible, because I cannot imagine GCC fellows to build 2 different implementation of the IEE754 decimal floating points, but according to that other SO post gcc support is still incomplete (at the time of the post, that is 2012).

You must dig in gcc documentation to find more because it is currently implemented as a gcc extension.

Community
  • 1
  • 1
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
1

We have it in this header file

#include <decimal/decimal>

and

Use it as std::decimal::decimal64 var;

decimal namespace is in namespace std

The source code can be found here for future reference

Sniper
  • 1,428
  • 1
  • 12
  • 28
  • the source code already says this is "ISO/IEC TR 24733" so it's just a TR and not a C++ feature. There's no `decimal` namespace in C++ and no `decimal/decimal` header yet – phuclv Jun 06 '22 at 02:28
0

I've asked around, and I think I've solved the problem. The equivalent of _Decimal64 in C is __decfloat64 in C++.

I present an example which allows the interop of decimals in C and C++. It may look more complicated than necessary, but I wanted to demonstrate how one might use it in a real project.

Here are the files:

File dec.h:

#pragma once

#ifdef __cplusplus
#include <decimal/decimal>
typedef std::decimal::decimal64::__decfloat64 Num;
#else
typedef _Decimal64 Num;
#endif

#ifdef __cplusplus
extern "C" {
#endif

Num get_num();
void print_num(Num n);

#ifdef __cplusplus
}
#endif

File decc.c:

#include "dec.h"

Num get_num()
{
    return 0.2DD;
}

File deccc.cc:

#include <decimal/decimal>
#include <iostream>
#include <iomanip> // for std::setprecision()

#include "dec.h"


void print_num(Num n)
{
    std::decimal::decimal64 d64(n);
    std::cout << std::setprecision(20) << std::decimal::decimal_to_float(d64) << std::endl;
    // Output is 0.20000000298023223877

}

int main()
{
    Num n = get_num();
    print_num(n);

    std::cout << ( 0.1 + 0.2 == 0.3) << std::endl; // false (0)
    std::cout << ( 0.1DD + 0.2DD == 0.3DD) << std::endl; // true (1)

    return 0;
}

File Makefile:

dec : decc.o deccc.o
        g++ decc.o deccc.o -o dec

decc.o : decc.c
        gcc -c decc.c

deccc.o : deccc.cc
        g++ -c deccc.cc

.PHONY : clean
clean :
rm -f *.o dec

You can find this files as a gist.

There does not seem to be any printing routines for decimals in the GNU compiler collection 6.3.1. I have my own ones that work to my satisfaction, so I am not too fussed at this stage. I think I saw a spec where the print directive for a decimal is a "D"; but again, it is not available in a released version.

The only output routine that GNU provides is if you first convert the decimal to a float, as in std::cout << std::setprecision(20) << std::decimal::decimal_to_float(d64) << std::endl;. You can see that it is not ideal, as errors creep in the conversion. The actual output is 0.20000000298023223877.

The internal representation of the decimals seems to be correct, though. If we ask that age-old question: does 0.1 + 0.2 == 0.3, we see that in floats the exe returns 0 for false.

However, if we make the comparison 0.1DD + 0.2DD == 0.3DD then the exe answers 1 for true.

Phew.

E_net4
  • 27,810
  • 13
  • 101
  • 139
blippy
  • 1,490
  • 1
  • 13
  • 22
  • Use std::decimal::decimal_to_double, rather than std::decimal::decimal_to_float; otherwise you will lose several digits of precision. – jorgbrown Jan 13 '20 at 10:40
  • **`_Decimal64` isn't a C type** until C23, before that it's just a GNU extension. And there's no `__decfloat64` in C++. Anything that begins with `__` is an extension of some compilers. Even `std::decimal::decimal64` isn't standard C++ type – phuclv Jun 05 '22 at 03:26
  • @phuclv I agree that this isn't standard C++, but your comment "Anything that begins with `__` is an extension of some compilers" is wrong. `__cplusplus`, for one, is not an extension -- but more than that, the C++ standard libraries use `__` prefixes all the time in their implementations to avoid conflicts with user-defined code since all names are reserved. That doesn't make it an extension; it just means that it's logically not meant to be used directly. – Human-Compiler Jun 05 '22 at 04:01