Thread overview
Arbitrary precision decimal numbers
3 days ago
frame
3 days ago
frame
2 days ago
Dom Disc
2 days ago
Dom Disc
2 days ago
Sergey
4 days ago

Is there any implementation in phobos of something similar to BigInt but for non-integers as well? If there isn't is there a dub package that does this, and if so, which one?

3 days ago

On Thursday, 4 August 2022 at 13:01:30 UTC, Ruby The Roobster wrote:

>

Is there any implementation in phobos of something similar to BigInt but for non-integers as well? If there isn't is there a dub package that does this, and if so, which one?

We have this:

https://code.dlang.org/search?q=decimal

I end up using BigInt instead on a custom wrapper that stores the precision hint. To calculate with any number, it need to convert each value to the same base (eg. storing 10.234 simply results in a BigInt with value 10234 and the precision hint of 3) and then forward the operation to BigInt.

3 days ago

On Friday, 5 August 2022 at 14:00:32 UTC, frame wrote:

>

On Thursday, 4 August 2022 at 13:01:30 UTC, Ruby The Roobster wrote:

>

Is there any implementation in phobos of something similar to BigInt but for non-integers as well? If there isn't is there a dub package that does this, and if so, which one?

We have this:

https://code.dlang.org/search?q=decimal

I end up using BigInt instead on a custom wrapper that stores the precision hint. To calculate with any number, it need to convert each value to the same base (eg. storing 10.234 simply results in a BigInt with value 10234 and the precision hint of 3) and then forward the operation to BigInt.

I'm already trying to make one, and I have a similar idea, but I ewant it extended to complex numbers.

Also, what about division and exponentiation. You can't just forward them to BigInt and get a good result, BigInt will just round to an integer for these two.

3 days ago

On Friday, 5 August 2022 at 14:03:36 UTC, Ruby The Roobster wrote:

>

Also, what about division and exponentiation. You can't just forward them to BigInt and get a good result, BigInt will just round to an integer for these two.

There are divMod() and powmod() for BigInt but I have no idea how precise they really are.

3 days ago

On Friday, 5 August 2022 at 14:11:10 UTC, frame wrote:

>

On Friday, 5 August 2022 at 14:03:36 UTC, Ruby The Roobster wrote:

>

Also, what about division and exponentiation. You can't just forward them to BigInt and get a good result, BigInt will just round to an integer for these two.

There are divMod() and powmod() for BigInt but I have no idea how precise they really are.

I'm currently working on an arbitrarily precise division algortihm based off of the done-by-hand standard algorithm, but I need to get it to work for complex numbers, which it's just not.

2 days ago

On Friday, 5 August 2022 at 14:25:39 UTC, Ruby The Roobster wrote:

>

I'm currently working on an arbitrarily precise division algortihm based off of the done-by-hand standard algorithm, but I need to get it to work for complex numbers, which it's just not.

I once did a completely inline implementation of xlcmplx based on an arbitrary precision float (in this context called xlfloat) in C++.
You only need to exchange xlfloat with your floatingpoint type:

class xlcmplx
{
	xlfloat Re, Im;
public:
	friend inline void swap(xlcmplx& a, xlcmplx& b) { swap(a.Re, b.Re); swap(a.Im, b.Im); }

	xlcmplx(const xlfloat& re =0, const xlfloat& im =0) : Re(re), Im(im) { }
	xlcmplx(const xlcmplx& c) : Re(c.Re), Im(c.Im) { }
	// two special "constructors":
	friend inline xlcmplx i(const xlfloat& x =1) { return xlcmplx(0,x); } // make pure imaginary number
	friend inline xlcmplx polar(const xlfloat& arg, const xlfloat& norm =1) { return (!norm || !arg) ? norm : xlcmplx(cos(arg),sin(arg)) *= norm; }

	uint32 Decimal(char* s, uint32 max) const; // string representation

	inline xlcmplx& operator=(const xlcmplx& c) { if(this != &c) Re = c.Re, Im = c.Im; return *this; }
	inline xlcmplx& operator=(const xlfloat& f) { Re = f, Im = 0; return *this; }

	inline xlcmplx& operator+() { return *this; } // dummy operator
	inline xlcmplx operator-() const { return xlcmplx(-Re, -Im); }
	inline xlcmplx& operator+=(const xlcmplx& c) { Re += c.Re; Im += c.Im; return *this; }
	inline xlcmplx& operator+=(const xlfloat& f) { Re += f; return *this; }
	inline xlcmplx& operator-=(const xlcmplx& c) { Re -= c.Re; Im -= c.Im; return *this; }
	inline xlcmplx& operator-=(const xlfloat& f) { Re -= f; return *this; }
	inline xlcmplx& operator*=(const xlcmplx& c) { xlfloat t = Re; t *= c.Re; t -= Im*c.Im; Im *= c.Re; Im += Re*c.Im; Re = t; return *this; }
	inline xlcmplx& operator*=(const xlfloat& f) { Re *= f; Im *= f; return *this; }
	inline xlcmplx& operator/=(const xlcmplx& c) { return *this *= inv(c); }
	inline xlcmplx& operator/=(const xlfloat& f) { Re /= f; Im /= f; return *this; }

	inline bool operator==(const xlcmplx& c) const { return Im == c.Im && Re == c.Re; }
	inline bool operator==(const xlfloat& f) const { return !Im && Re == f; }
	inline bool operator!=(const xlcmplx& c) const { return Im != c.Im || Re != c.Re; }
	inline bool operator!=(const xlfloat& f) const { return !!Im || Re != f; }

	friend inline const xlfloat& real(const xlcmplx& c) { return c.Re; }
	friend inline const xlfloat& imag(const xlcmplx& c) { return c.Im; }
	friend inline xlfloat norm(const xlcmplx& c) { return c.Im ? c.Re ? sqr(quad(c.Re)+quad(c.Im)) : abs(c.Im) : abs(c.Re); }
	friend inline xlfloat arg(const xlcmplx& c) { return atan2(c.Re, c.Im); } // an angle in [0..2*pi[

	friend inline xlcmplx conj(xlcmplx c) { c.Im.neg(); return c; }
	friend inline xlcmplx inv(const xlcmplx& c) { xlfloat t = quad(c.Re); t += quad(c.Im); return conj(c) /= t; }
	friend inline xlcmplx quad(const xlcmplx& c) { return xlcmplx(quad(c.Re)-quad(c.Im),(c.Re*c.Im)<<1); }
	friend inline xlcmplx exp(const xlcmplx& c) { return c.Im ? xlcmplx(cos(c.Im), sin(c.Im)) *= exp(c.Re) : exp(c.Re); }
	friend inline xlcmplx sin(const xlcmplx& c) { return c.Im ? c.Re ? xlcmplx(sin(c.Re)*cosh(c.Im), cos(c.Re)*sinh(c.Im)) : i(sinh(c.Im)) : sin(c.Re); }
	friend inline xlcmplx cos(const xlcmplx& c) { return c.Im ? c.Re ? xlcmplx(cos(c.Re)*cosh(c.Im), sin(c.Re)*sinh(c.Im)) : cosh(c.Im) : cos(c.Re); }
	friend inline xlcmplx ln(const xlcmplx& c) { return xlcmplx(ln(norm(c)), arg(c)); } // main value - multiples of 2*pi*i added are also valid results
};

inline bool operator==(const xlfloat& f, const xlcmplx& c) { return c == f; }
inline bool operator!=(const xlfloat& f, const xlcmplx& c) { return c != f; }

inline xlcmplx operator+(xlcmplx a, const xlcmplx& b) { return a += b; }
inline xlcmplx operator+(xlcmplx a, const xlfloat& b) { return a += b; }
inline xlcmplx operator+(const xlfloat& a, xlcmplx b) { return b += a; }
inline xlcmplx operator-(xlcmplx a, const xlcmplx& b) { return a -= b; }
inline xlcmplx operator-(xlcmplx a, const xlfloat& b) { return a -= b; }
inline xlcmplx operator-(const xlfloat& a, const xlcmplx& b) { return -b += a; }
inline xlcmplx operator*(xlcmplx a, const xlfloat& b) { return a *= b; }
inline xlcmplx operator*(xlcmplx a, const xlcmplx& b) { return a *= b; }
inline xlcmplx operator*(const xlfloat& a, xlcmplx b) { return b *= a; }
inline xlcmplx operator/(xlcmplx a, const xlcmplx& b) { return a /= b; }
inline xlcmplx operator/(xlcmplx a, const xlfloat& b) { return a /= b; }
inline xlcmplx operator/(const xlfloat& a, const xlcmplx& b) { return xlcmplx(a) /= b; }

inline xlcmplx pow(const xlcmplx& c, const int exp) { return polar(arg(c)*exp, pow(norm(c), exp)); }
inline xlcmplx pow(const xlcmplx& c, const xlfloat& exp) { return polar(arg(c)*exp, pow(norm(c), exp)); }
inline xlcmplx log(const xlcmplx& c, const uint32 base = 10) { return ln(c) /= ln(number(base)); }

You can also get the implementation of xlfloat, if you like - but that one is NOT completely inline and much longer :-D

2 days ago

On Saturday, 6 August 2022 at 11:25:28 UTC, Dom Disc wrote:

>

I once did a completely inline implementation of xlcmplx

Sorry, one function is NOT inline:

>
class xlcmplx
{
	uint32 Decimal(char* s, uint32 max) const; // string representation
}

But you should forget about that, because D has much better methods to create a string. In fact good enough that also this function could have been inline... but in D the whole concept of headers is superfluous, so who cares.

2 days ago

On Thursday, 4 August 2022 at 13:01:30 UTC, Ruby The Roobster wrote:

>

Is there any implementation in phobos of something similar to BigInt but for non-integers as well? If there isn't is there a dub package that does this, and if so, which one?

Also you could find usefull such projects:

http://mir-algorithm.libmir.org/mir_bignum_decimal.html

https://github.com/huntlabs/hunt-extra/blob/2d286f939193fc0cd55c799906f7657cec502dc8/source/hunt/math/BigDecimal.d