Convert Int<>/UInt<> to double with ttmath?
I've had a look though the code and there doesn't seem to be any built in way of converting Int<> or UInt<> to a double (floating point). Is it possible you could add this?
I thought about adding it myself, but I'm not entirely clear on how to do it and I'm worried about bugs. I suspect its a slightly odd thing to do, but I use it extensively in my software. I have a lot of 128-bit counters, but I need them in double precision floating point to perform further processing on them.
It would also be nice, but not critical for me, if you also supported conversions between these types and Microsoft's __int64. You library does look really good though, and amazingly small.
I don't plan to add conversions to double to UInt or Int. I don't want to mix integer with floating
But you can do it by in this way:
template<unsigned int size>
int conv_to_double(const Int<size> & in, double & out)
Big<1, size> temp(in);
how to use it:
Int<4> a = "-646273692837642344";
if( conv_to_double(a, b) )
std::cout << "carry" << std::endl;
std::cout << b << std::endl;
Conversions to 64 bit integer is a good thing, I add it to my TODO list but instead of __int64
I will probably use 'long long'.
I've successfully integrated ttmath into my software and have some feedback for you.
I've had a number of compilation problems, but I'll start with some comments/suggestions.
I hope this is clear, but its getting really late and I wanted to get it off...
I did a very simple benchmark against another large integer library, MIRACL, and was most surprised to find ttmath uses half the memory and is about 5 to 10 times faster. Nice.
I was mistaken about converting to/from 64 bit ints not be important - I use it a lot and it was painful adding it.
It would be really nice if ToString() returned the string instead of taking it as a parameter, as its easier to use.
It would be nice if you provided cast operators to convert to other types. You couldn't return carry flags, but I don't understand why you do this instead of exceptions. Perhaps I'm misunderstanding something, but since its a template library and size's are set a compile time, then if there's a carry then its a big problem - in my application I just give up and stop. If I wanted to use the carry to extend the size, then I'd just make the size bigger in the first place, or I wanted to make it dynamic I'd use a different library that's designed for it. I think that having carry's makes the api more difficult to use.
I understand your point about converting Int<> to double, but as a philosophical and practical point C/C++ does it (converts between int and float) and its really useful. I'd argue that you could say the same thing about mixing strings with a integer library, but ToString() is clearly necessary. I've done it, as you suggested (thanks), so I guess it really doesn't matter.
Since you use the name Int<>, why not Float<> instead of Big<> ? The name Big doesn't have carry any real meaning - it could just as easily be an integer, or anything else. Along the same lines, why not Unsigned<> instead of UInt<>, then all the names would be based on language names.
Just a thought, but if you provided a C++ implementation of the assembler code it would provide easy compatibility with other platforms. For example, I'll want to go to 64-bit windows at some point, and it would be a lot easier if it worked, then I could worry about performance later. It would probably also be a lot easier for others to port the code to new platforms if they could get a C++ version going first.
I use Visual Studio 2008 and compile with warning level 4.
I'm also using Boost and get some errors compiling. It's where you have used
assembler (in ttmathuint_x86.h, around lines 193, 342, 550) like this
There seems to be some conflict with Boost, but it's easily fixed by renaming 'end' to 'ttmath_end'.
An example of the error message is
1>c:\program files\ttmath\ttmath\ttmathuint_x86.h(219) : error C2244:
'boost::end' : unable to match function definition to an existing
1> c:\program files\ttmath\ttmath\ttmathuint_x86.h(193) : while
compiling class template member function 'ttmath::uint
1> c:\program files\ttmath\ttmath\ttmathint.h(64) : see reference to
class template instantiation 'ttmath::UInt<value_size>' being compiled
1> .\Main.cpp(741) : see reference to class template instantiation
'ttmath::Int<value_size>' being compiled
1>c:\program files\ttmath\ttmath\ttmathuint_x86.h(219) : error C2415:
improper operand type
I also got some other warnings like this
1>c:\program files\ttmath\ttmath\ttmathobjects.h(247) : warning C4673:
throwing 'ttmath::RuntimeError' the following types will not be considered
at the catch site
1>c:\program files\ttmath\ttmath\ttmathobjects.h(247) : warning C4670:
'ExceptionInfo' : this base class is inaccessible
ttmathtypes.h, line 352, 385
This was fixed by making ExceptionInfo public - I'm not really sure whats going on here as I don't use these language features much
class ReferenceError : public std::logic_error, public ExceptionInfo
class RuntimeError : public std::runtime_error, public ExceptionInfo
I get a lot of warning's like this
1>c:\program files\ttmath\ttmath\ttmathuint.h(1000) : warning C4127:
conditional expression is constant
The relevant line of code is
if( value_size > 2 )
It's a bit stupid on Microsoft's part as a template argument is by
definition constant. This link has more
I disabled it by placing these at the start and end of the file
#pragma warning(default : 4127 )
#pragma warning(disable : 4127)
I also get this warning
1>c:\program files\ttmath\ttmath\ttmathuint.h(1476) : warning C4100:
'divisor_table_id' : unreferenced
The relevant code is
bool Div2_DivisorGreaterOrEqual( const UInt<value_size> &
UInt<value_size> * remainder,
uint table_id, uint index,
uint divisor_table_id, uint divisor_index )
The fix was to just remove the name.
And this warning
1>c:\program files\ttmath\ttmath\ttmathuint.h(2350) : warning C4244: '=' :
conversion from 'ttmath::uint' to 'char', possible loss of data
was this line of code
character = DigitToChar( rem );
void ToString(std::string & result, uint b = 10) const
I just added a cast
character = (char) DigitToChar( rem );
If you make these any of these changes I'd be happy to test them for you if you let me know.
Lastly, thanks for making this library available. Its a nice piece of work.
Nice to hear that ttmath is faster than other library, if you make some performance tests make sure that macro TTMATH_RELEASE is defined. If the macro is defined that the library is sometimes even twice faster.
Conversions from/to 64 bit integer (for UInt<>) will be in 0.9.x branch. There'll be conversions from/to double too. You are very convincing.
Method ToString() is getting the string as a parameter in order to help the compiler make a better code. Consider
UInt<10> v1, v2, v3;
v1.ToString(result); std::cout << result;
v2.ToString(result); std::cout << result;
v3.ToString(result); std::cout << result;
In such a case the dynamic memory for result is reused. But I'll probably add such a method in 0.9.x branch.
I will not provide any cast operators. I've got bad experiences with cast operators. When such operators are defined then everything can use (be converted) to everything. This is error-prone way.
Exceptions for carry will be added in 0.9.x.
What about the name Big<> hmm, I'm not good on creating names :)
But Int<> seems to be a better name than Integer<>, it's shorter. I prefer names of types to be short and simple.
From version 0.8.4 there is a pure C++ implementation of all the methods with asm code. Just declare macro TTMATH_NOASM and the C++ version will be used.
I got rid of all the warnings you have reported, thanks for this, all changes are in repository:
svn co svn://slimaczek.pl/publicrep/ttmath/trunk
You said that Int/UInt to double would be available in the 0.9.x branch. I've downloaded 0.9.3 and I can't see any ToDouble methods in the ttmathint.h and ttmathuint.h files. Is there something I'm missing?
I have to investigate this but not now, give me a few days.