Skip to content

Conversation

@LdBeth
Copy link

@LdBeth LdBeth commented Nov 29, 2021

Resolves proposal #69

Ready for review.

@LdBeth
Copy link
Author

LdBeth commented Nov 29, 2021

The specification followed (partially, to stay compatible with Float) is available at http://speleotrove.com/decimal

@hebisch
Copy link
Collaborator

hebisch commented Dec 1, 2021 via email

@LdBeth
Copy link
Author

LdBeth commented Dec 1, 2021

Thank you for the review comments, @hebisch

For this you will need changes to
src/interp/compiler.boot, probably in compSel1 and constant_coerce.

These are mainly hacks to produce double float literals for the Common Lisp compiler.
Besides, I haven't figure out a way to add the support there without breaking the rest of the code.

Unless you have strong reason to do
otherwise the simplest approach is to convert to float,
use float function and convert back.

Converting to Float is easy, however converting back without significant precision loss is not straight
forward and requires complex computations.

Say, 1.2, is 177088743107611695514*2^- 67 which gives 1.1999993663_703848278
when feed to the float(m, e, p)$DecimalFloat function. Although convert10 inside Float
can do the job correctly, there are at least 2 problems:

  1. elision of trailing zeros. The General Decimal Arithmetic requires using full precisions when the result is inexact.
  2. different rounding mode. The Float uses binary round to even, while DecimalFloat uses round up half. exp 1.3 gives 3.6692966676_192442204 in binary float, and in decimal it can gives 3.6692966676_192442205

the General Decimal Arithmetic has these special requirements on log10, power and exp so I have
adapted the algorithm a little. For the rest of the elementary functions they are unspecified, using binary
implementation should be fine.

@hebisch
Copy link
Collaborator

hebisch commented Dec 1, 2021 via email

@LdBeth
Copy link
Author

LdBeth commented Dec 2, 2021

This is massive error, you have only about 20 bits of accuracy.
In such case I would look for bugs in decimal artitmetic routines.

Indeed, this due to a bug that I didn't given enough precision in division when the length
of right operand is large.
With the correction been made float(177088743107611695514, -67, 2)$DecimalFloat
gives 1.2000000000_000000000.

Given that correction is made, I feel no objection to using binary float for elementary functions.
I'll try following the roundExactlyIfCan approach.

I plan to implement more functions using similar
principle as used in exp1 (that is computing rational
approximations purely in integer arithmetic).

Yes, please do so. btw right now I find log(x)$Float gives bad approximation when x is close enough to 1

(16) -> log 1.0000001

   (16)  0.9999999500_0002764028 E -7
                                                                  Type: Float

Which is 0.999999950000003333333 with higher precision.

@hebisch
Copy link
Collaborator

hebisch commented Dec 2, 2021 via email

@hebisch
Copy link
Collaborator

hebisch commented Dec 2, 2021 via email

@LdBeth
Copy link
Author

LdBeth commented Dec 2, 2021

Note that ATM dvide is affectively doing its own rounding towards
-infinity. Which means that it does not agree with rule for
rounding that you gave.

My code for dvide is different from Float, the basic idea is:

  1. integer division, if it can do exact division then return exact result.
  2. it is guaranteed that LENGTH y.mantissa - LENGTH r is positive after step 1.
  3. get the fraction r / y with exceeded precision. remove trailing zeros.
  4. adds up integer part with the fraction part

I used rounded addition by calling + at the end, so the result is rounded like any other basic arithmetic operators
in DecimalFloat domain. Albeit mine is much slower, the goal is to provide exact result when the result is not normalized,
as required in the General Arithmetic spec.

So far I'm looking at other methods for log, it might be ended up using different algorithms in DecimalFloat.

@hebisch
Copy link
Collaborator

hebisch commented Dec 2, 2021 via email

@LdBeth
Copy link
Author

LdBeth commented Dec 3, 2021 via email

@hebisch
Copy link
Collaborator

hebisch commented Dec 3, 2021 via email

@LdBeth
Copy link
Author

LdBeth commented Dec 3, 2021 via email

@hebisch
Copy link
Collaborator

hebisch commented Dec 4, 2021 via email

@LdBeth
Copy link
Author

LdBeth commented Dec 4, 2021 via email

@hebisch
Copy link
Collaborator

hebisch commented Dec 4, 2021 via email

@LdBeth
Copy link
Author

LdBeth commented Dec 4, 2021 via email

@hebisch
Copy link
Collaborator

hebisch commented Dec 6, 2021 via email

@LdBeth
Copy link
Author

LdBeth commented Dec 22, 2021

sorry for the delay of reply, I was been busy for end term stuff for a while.

My point was that using abs(x) is
obviously correct and there seem to be no advantage in not using it.

Sure, I'll have that fixed.

AFAICS the following (untested) implements the spec:

That looks good. I'll use that for the definition of dvide for now.

For sqrt IIUC they require round-half-even even if
another rounding mode is in use for other operations.

Yes, however the spec does not mention what to do if the precision
of operand is higher than current precision. If we insist on correct rounding
in that case, I guess I have to do a correct implementation of round-half-even.

@hebisch
Copy link
Collaborator

hebisch commented Jan 14, 2022 via email

Improve conformance to decarith; add testcase

And fix Makefile.in update.

fix bug in division

DecimalFloat support in SPAD

fix obvious problems in divide and sqrt

fix sqrt

new exp wip

still need exp1

add cached exp1

stage changes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants