Computer Arithmetic Emulation And Rounding 
	Error Analysis

Abstract
The presentation describes a package to emulate computer arithmetic and, as an illustration of 
	one application, applies the package, using Mathematica to compute the truth, to two simple 
	non-analytic/experimental rounding-error-analysis examples. The first a classical demonstration 
	of finite word length effects: accumulation of rounding error from incrementing within a loop. 
	The second compares the performance of five variations of the quadratic formula for rounding 
	and chopping.

Bill Schwartz, SchwartzWJ@HotMail.com

11/3/04: parts of the spoken-portion of the presentation were added as text to this notebook.

Initial Comments

The abstract concisely describes the flow and content of the presentation.

My package is somewhat different from Mathematica's computer arithmetic package. I usedMathematica's 
	several years ago--around 1996; I found it rather limited for my needs, didn't like the results I got, 
	and didn't care for the package's implementation; this is not to disparage it, it just didn't satisfy my 
	needs, so I developed my own. Besides my package being more extensive in certain ways, there at least 
	two of the fundamental differences between my package and Mathematica's. One, my package more 
	or less relies on RealDigits, and Mathematica's package doesn't use RealDigits; two, my package always 
	shows the digits in the mantissa of a computer number, and Mathematica's package doesn't--it just 
	shows the mantissa's value. However, if one is satisfied with Mathematica's current implementation, 
	then this talk may prove disappointing.

A comment about the graphs used in the presentation. Some graphs, if not all, have been scaled using a 
	logarithmic function to allow all the points fit on one graph, so spatial distances are distorted. Therefore, 
	one point may be orders of magnitude smaller or larger than another point, but it may not appear that way.

Background

My purpose for emulating computer arithmetic in a Mathematica package is to evaluate the rounding-error
	of algorithms in a non-analytic/experimental way; however, that doesn't exclude the possibility of other
	applications.

The idea occurred to me while doing numerical analysis as a research assistant in graduate school. We used 
	mostly analytical methods for rounding error analysis, and, for most algorithms this was--at least for me--
	rather difficult and/or intractable. For doing experimental rounding error analysis, you needed the
	truth/correct-value, and around 1980 systems like Mathematica, which could do non-decimal computations 
	enabling you to compute the truth, didn't exist; or if they did exist, the group I was working with wasn't 
	aware of them. You either computed the truth by hand or knew it for special cases. Also, if your situation 
	allowed it, there was approximating the truth by using a greater number of bits (e.g, double precision 
	compared to single precision), but all these ways weren't completely satisfying for me. Then, while working, 
	I started to receive problems like: one, for the given inputs, the output must be accurate to within five mils; 
	is the algorithm meeting this requirement. Two, what is the least number of base-two digits one needs to 
	make the given algorithm accurate to five base-ten digits; at the time, I believe the last question involved 
	production of hardware, so reducing costs and /or size may have been important. Sometimes problems like 
	these were dismissed for various reasons, otherwise, to solve such problems, one did a crude analysis, adapted 
	some know analysis from the literature, used double precision compared to single precision, or, in special 
	circumstances, computed the truth or obtained physical measurements which could be compared to the 
	algorithm's values. Then several years after Mathematica was developed, receiving one such problem, and 
	wanting to evaluate my own algorithms and others without resort to difficult analytical methods, I found 
	the time to develop this package with which one could do experimental rounding-error-analysis.

Status Of Computer Arithmetic Emulation Package

The package was initially created in base ten because it was expedient. Once there was a minimal 
	package to use, one could consider a better, more ambitious package, and an upgrade was completed  
	which allows any integer base greater than 1--not just base 10 (since it essentially depends on RealDigits, 
	it should function for any real number greater than 1, but I haven't verified this). The package 
	only handles real numbers and doesn't check for overflow and underflow; however, there are 
	work-arounds to these deficiencies. For example, computing the real and  imaginary parts of a 
	complex number separately. What should be the final upgrade will be to incorporate complex 
	numbers, overflow, and underflow. Presently, the package is in a testing stage due to some minor 
	improvements made.

I had hoped to finish the package and do this presentation for a Developer's Conference which I expected
	this coming spring--like the last one--but the Conference was held now and so things are incomplete.

Caveats

The limitations of the package are essentially the limitations of Mathematica. I believe the only 
	Mathematica function the package uses, which depends on a base, is RealDigits, so it's probably 
	limited by RealDigits. However I could be wrong about this, since I haven't checked into the 
	limitations thoroughly.

If you're doing experimental rounding error analysis, you must have the truth for comparison, and, 
	as I've mentioned, Mathematica can provide this: it does non-decimal computations. However, those 
	of you who have used Mathematica in this way know that this can take much time and memory. 
	Therefore, if your algorithm is large and/or complex, you may have problems obtaining the truth you 
	need; then, if possible, you may have to divide your algorithm into pieces. I might also add that there 
	is the extra time due to the package functions to consider.

I find the package most useful for doing experimental rounding error analysis when the input ranges 
	are all in reasonably sized intervals, or you have an idea over what intervals the algorithm may have 
	problems. This way you can take good representative samples of the intervals.

Finally, although one could probably use Mathematica in conjunction with actual hardware and a 
	formal programming language to do experimental rounding error analysis, I find the package more 
	convenient and versatile: the notebook conveniently holds everything, no need to deal with a formal 
	programming language, and you have more control. Also, at least in my case, sometimes part of the 
	hardware formal-programming-language combination does not exist or is not available.

Computer Arithmetic Emulation Package Concepts

Regarding the fidelity of the concepts, you will have to decide if it is acceptable to you.

Let (Subscript[f, c]), and (Subscript[f, e]) denote, respectively, a computer binary operation and a true binary operation; let F denote 
	chopping or rounding. If x and y are two computer numbers, one defines 

																						(Subscript[f, c])(x,y) = F( (Subscript[f, e])(x,y) ).

	Example: using rounding, let ⊗denote the computer multiplicative product, × the true multiplicative 
		product, and let x and y be two computer numbers; then 

											x⊗y = round(x × y) .  Take the true multiplicative product and round it.
	
For functions like sine(x), cosine(x), tangent(x), etc., let (Subscript[g, c])denote the computer function and (Subscript[g, e]) the true 
	function, then if x is a computer number, one defines

																						(Subscript[g, c])(x)=F( (Subscript[g, e])(x) ).

	Example: using chopping, let √ denote the computer square root,  \(\(\(\@\ \)\(\ \)\)\)the true square root, and let x 
		be a computer number; then 

														√x  = chop((Sqrt[x ])) .  Take the true square root and chop it.

A computer number in the emulation has the form {m, e, s}, where m is the mantissa--left justified--e is 
	the exponent, and s is the sign (1 for plus, -1 for negation). { {1, 11, 10, 3, 4 ,5}, 2, 1} could be a positive 
	base 12 number of 6 mantissa-digits (eliminating the exponent 2 would move the decimal point to 
	between the 11 and 10). { {1, 11, 10, 3, 4 ,5}, 2, -1} could be a negative base 12 number of 6 mantissa-digits, 
	and a 6 digit-mantissa zero has the form {{0, 0, 0, 0, 0, 0}, 0, 0}. The number of digits in the exponent is 
	not considered; in the future that will be handled by implementing overflow and underflow. The integer
	base for the computer number and the number of mantissa digits can be specified, and all numbers 
	within a computer number are base ten--regardless of the base.

														 													{m, e, s}

																							{ {1, 11, 10, 3, 4 ,5}, 2, 1}

																							{ {1, 11, 10, 3, 4 ,5}, 2, -1}

																							{{0, 0, 0, 0, 0, 0}, 0, 0}

Also, there are many algorithms in the package for converting to and from computer numbers.

Package Application To Non-Analytic/Experimental Rounding 
	Error Analysis--Two Simple Examples

I might point out that the examples are used to show how the package works and its possibilities, and 
	they are not meant to be impressive in a computer science or mathematical sense—nothing earth 
	shattering. I just felt that using these examples would be the simplest way to demonstrate the package.

Needs["BS`REA`"]

Needs["Utilities`Notation`"]

One needs the Notation package to display the package functions in an aesthetic form, like for this 
	presentation, otherwise, there is a more practical approach which I will demonstrate.

Since they are needed in the following, one now defines absolute error and relative error. Let t be the 
	true value expected from a given algorithmic process and a the actual value obtained from the 
	algorithmic process; one define absolute error, ae, and relative error, re, as follows:

												                            ae=|a-t|                    re=| (a-t)/t |  .

Generally, I tend to use absolute error when there is one truth for comparison, and relative error otherwise.

classical demonstration of finite word length effects: accumulation of rounding error from incrementing within a loop

Do loop to add 8/9 one thousand times.

Below, notice that I use the Notation package in a rather indirect way; this is due to some problems
	believed to be caused by the way I define options for my package functions.

Clear[h1, h2, h3, h4]
h1[x_List, y_List] := 
      RDS$AddR[x, y]
InfixNotation[\(+\_r\),h1]
h3[x_List, y_List] := RDS$DivR[x, y]
InfixNotation[\(/\_r\),h3]

Clear[g1, g2, g3, g4]
g1[x_List, y_List] := 
      RDS$AddC[x, y]
InfixNotation[\(+\_c\),g1]
g3[x_List, y_List] := RDS$DivC[x, y]
InfixNotation[\(/\_c\),g3]

GlobalBase = 2;
GlobalDigits = 
        2;
precis = 14;
eightr = 
        NumAllToRDS$R[8];
niner = 
        NumAllToRDS$R[9];
eightc = NumAllToRDS$C[8];
ninec = NumAllToRDS$C[9]; 
zero = NumAllToRDS$R[0];

tott = 0;
\(Do[
	tott = tott + 8/9, 
{i, 1000}
 (*EndDo*) ]\)

totr = zero;
Do[
	totr=totr\(+\_r\)(eightr\(/\_r\)niner),
{i, 1000}
  ]

totc = zero;
Do[
totc=totc\(+\_c\)(eightc\(/\_c\)ninec),
{i, 1000}
  ]

timing results for Intel Pentium III 1000MZ processor

Timing[
		totr = zero;
		Do[
			totr=totr\(+\_r\)(eightr\(/\_r\)niner),
		{i, 1000}
		  ]
  ]

Rounding results.

{tott, totr} = {tott, RDS$ToRational[totr]}
{SetPrecision[tott, precis],    SetPrecision[totr, 
        precis]}
Abs[SetPrecision[totr - tott, precis]]

why the problem (rounding)

Below, notice that besides specifying the base and mantissa-length globally, one can supply them locally 
	as arguments to the package functions.

Notice, below, that one gets stuck at 8.

\(\(\(NumAllToRDS$R[8, 2, 10]

    NumAllToRDS$R[9, 2, 10]

    temp1 = 
      RDS$DivR[eightr, 
        niner]\)\(\ \ \ \ \ \ \ \ \ \ \ \ \)\( (*the\ computer\ number\ 8/
          9*) \)\)\)

totr = zero
totr=totr\(+\_r\)(eightr\(/\_r\)niner)
totr=totr\(+\_r\)(eightr\(/\_r\)niner)
totr=totr\(+\_r\)(eightr\(/\_r\)niner)
totr=totr\(+\_r\)(eightr\(/\_r\)niner)
totr=totr\(+\_r\)(eightr\(/\_r\)niner)
totr=totr\(+\_r\)(eightr\(/\_r\)niner)
totr=totr\(+\_r\)(eightr\(/\_r\)niner)

Chopping results.

{tott, totc} = {tott, RDS$ToRational[totc]}
{SetPrecision[tott, precis],    SetPrecision[totc, 
        precis]}
Abs[SetPrecision[totc - tott, precis]]

why the problem (chopping)

Notice, below, that one gets stuck at 4.

\(\(\(NumAllToRDS$C[8, 2, 10]

    NumAllToRDS$C[9, 2, 10]

    temp1 = 
      RDS$DivC[eightc, 
        ninec]\)\(\ \ \ \ \ \ \ \ \ \ \ \ \ \)\( (*the\ computer\ number\ 8/
          9*) \)\)\)

totc = zero
totc=totc\(+\_c\)(eightc\(/\_c\)ninec)
totc=totc\(+\_c\)(eightc\(/\_c\)ninec)
totc=totc\(+\_c\)(eightc\(/\_c\)ninec)
totc=totc\(+\_c\)(eightc\(/\_c\)ninec)
totc=totc\(+\_c\)(eightc\(/\_c\)ninec)
totc=totc\(+\_c\)(eightc\(/\_c\)ninec)
totc=totc\(+\_c\)(eightc\(/\_c\)ninec)

incrementing within a loop results for several different mantissa lengths (base 2)

Digits will always refer to the number of digits in the mantissa.

({{digits, "rounded absolute-error", \(\(\ \ \ \ \ \ \ \ \ \ \)\(chopped\ "absolute-error"\)\)}, {"2", 880.8888888888888888889`9.999999999999998, \(\(\ \ \ \ \ \ \ \ \ \ \)\(\(884.8888888888888888889`10.000000000000004\)\(
\)
                \)\)}, {"4", 872.8888888888888888889`9.999999999999998, \(\(\ \ \ \ \ \ \ \ \ \ \)\(\(880.8888888888888888889`9.999999999999998\)\(
\)
                \)\)}, {"8", 632.8888888888888888889`10.000000000000004, \(\(\ \ \ \ \ \ \ \ \ \)\(\(760.8888888888888888889`10.000000000000004\)\(
\)
                \)\)}, {"16", 1.4548611111111111111111111111`9.999999999999998, \(\(\ \ \ \ \ \ \ \ \ \)\(\(7.9670138888888888889`9.999999999999998\)\(
\)
                \)\)}, {"32", 0.0000360541873508029513888889`10.000000000000004, \(\(\ \ \ \ \ \ \ \ \ \)\(0.0000474982791476779513888889`10.000000000000004\)\)}})

comparing the performance of five variations of the quadratic formula, for 
	rounding and chopping, using one set of quadratic polynomial coefficients

for the quadratic roots, I will be referring to them as root1 and root2, and they will always refer to 
	the same numbers; for example, if the roots are 2 and 4, root1 will always refer to 2 and root2 will 
	always refer to 4—no name switching.

Clear[h1, h2, h3, h4]
h1[x_List, y_List] := 
      RDS$AddR[x, y]
InfixNotation[\(+\_r\),h1]
h2[x_List, y_List] := RDS$MulR[x, y]
InfixNotation[\(*\_r\),h2]
h3[x_List, y_List] := RDS$DivR[x, y]
InfixNotation[\(/\_r\),h3]
h4[x_List, y_List] := RDS$SubR[x, y]
InfixNotation[\(-\_r\),h4]

Clear[g1, g2, g3, g4]
g1[x_List, y_List] := 
      RDS$AddC[x, y]
InfixNotation[\(+\_c\),g1]
g2[x_List, y_List] := RDS$MulC[x, y]
InfixNotation[\(*\_c\),g2]
g3[x_List, y_List] := RDS$DivC[x, y]
InfixNotation[\(/\_c\),g3]
g4[x_List, y_List] := RDS$SubC[x, y]
InfixNotation[\(-\_c\),g4]

Clear[f1, f2, f3, f4]
f1[x_List, y_List] := 
      RDS$GE[x, y]
InfixNotation[≥,f1]
f2[x_List, y_List] := RDS$GT[x, y]
InfixNotation[>,f2]
f3[x_List, y_List] := RDS$LE[x, y]
InfixNotation[≤,f3]
f4[x_List, y_List] := RDS$LT[x, y]
InfixNotation[<,f4]

Clear[Mi, abs, Si]
Mi[x_] := RDS$Minus[x]
abs[x_] := RDS$Abs[x]
Si[x_] := RDS$Sign[x]

solve	(ax^2) + bx + c = 0 with a=45/11,    b=211/12,   and c=3/2  
	for a form of the quadratic formula using rounding (base 2)

Clear[§, cos, sin, tan, cot, arccos, arcsin, arctan, 
      arctan2]
§[x_] := RDS$SR$R[x]
cos[x_] := RDS$CosR[x]
sin[x_] := RDS$SinR[x]
tan[x_] := RDS$TanR[x]
cot[x_] := RDS$CotR[x]
arccos[x_] := RDS$ArcCosR[x]
arcsin[x_] := RDS$ArcSinR[x]
arctan[x_] := RDS$ArcTanR[x]
arctan2[x_, y_] := RDS$ArcTan2R[x, y]

Below, some package functions, which were set up in aesthetic form, are set up in non-aesthetic form, 
	and you'll see why in the following.

Clear[A, S, M, Q]
A[x_, y_] := RDS$AddR[x, y]
S[x_, y_] := RDS$SubR[x, y]
M[x_, y_] := RDS$MulR[x, y]
Q[x_, y_] := RDS$DivR[x, y]

{a, b, c} = {45/11, 211/12, 3/2};

GlobalBase = 2;
GlobalDigits = 2;
ac = NumAllToRDS$R[a];
bc = NumAllToRDS$R[b];
cc = NumAllToRDS$R[c];
twoc = NumAllToRDS$R[2];
fourc = NumAllToRDS$R[4];
zeroc = NumAllToRDS$R[0];
monec = NumAllToRDS$R[-1];

form 1

solve (ax^2) + bx + c = 0 for x:

\(root1 = \(\(\(-b\) - \@\(b\^2 - 4\ a\ c\)\)\/\(2\ a\)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ root2 = \(\(-b\) + \@\(b\^2 - 4\ a\ c\)\)\/\(2\ a\)\)\)

root1t = (-Sqrt[b*b - (4*a)*c] - b)/(2*
              a);
root2t = (Sqrt[b*b - (4*a)*c] - b)/(2*a);

root1r=(Mi[§[(bc\(*\_r\)bc)\(-\_r\)((fourc\(*\_r\)ac)\(*\_r\)cc)]]\(-\_r\)bc)\(/\_r\)(twoc\(*\_r\)ac);
root2r=(§[(bc\(*\_r\)bc)\(-\_r\)((fourc\(*\_r\)ac)\(*\_r\)cc)]\(-\_r\)bc)\(/\_r\)(twoc\(*\_r\)ac);

One takes the Mathematica algorithm for the truth and obtains an aesthetic form for the
	emulation by using rules; some formatting remains.

Clear[root1r, 
      root2r]
\(temp1 = 
		Hold[
				root1t = \((\((\(-Sqrt[
                      b*b - \((4*a)\)*c]\))\) - b)\)/\((2  
                a)\); 
				root2t = \((Sqrt[b*b - \((4*a)\)*c] - 
                b)\)/\((2*a)\); 
		 (*EndHold*) ]\)
				\(\(\(//.\)\({Times[\(-1\), a_] :> 
                        M1[a]}\)\) /. 
				{4 :> fourc, 2 :> twoc}\)//.
				{Plus[a1_, M1[b1_]]:>(a1\(-\_r\)b1)}/.
				(M1[a_]\(-\_r\)b_):>(M1[b]\(-\_r\)a)//.
				{Times[Plus[a_], Power[b_, -1]]:>(a\(/\_r\)b)}/.
				{HoldPattern[c] :> cc, HoldPattern[b] :> bc, 
            HoldPattern[a] :> ac}//.
				{Sqrt -> §,M1 -> Mi,Times[a1_, b1_]->(a1\(*\_r\)b1),Plus[a2_, b2_]->(a2\(+\_r\)b2),
				-1 :> monec,HoldPattern[root1t] :> root1r,HoldPattern[root2t] :> root2r}

One usually doesn't need an aesthetic form so one can substitute the package functions or
	a simpler form in the Mathematica algorithm for the truth; a simpler form still allows
	the resulting emulation algorithm to be somewhat readable.

Clear[root1r, root2r]
\(temp1 = 
		Hold[
				root1t = \((\((\(-Sqrt[
                      b*b - \((4*a)\)*c]\))\) - b)\)/\((2  
                a)\); 
				root2t = \((Sqrt[b*b - \((4*a)\)*c] - 
                b)\)/\((2*a)\); 
		 (*EndHold*) ]\)
\(				\(\(\(\(\(//.\)\({Plus[a1_, Times[\(-1\), b1_]] :> 
                  S[a1, b1]}\)\) //. 
				S[Times[\(-1\), a_], b_] :> 
              S[Mi[b], a]\) //. 
				{Times[Plus[a_], 
                Power[b_, \(-1\)]] :> Q[a, b]}\) /. 
				{HoldPattern[
              c] :> cc}\) /. 
				{Sqrt -> §, Times -> M, 
        Plus -> A, 4 :> fourc, 
        2 :> twoc, \(-1\) :> monec, 
				HoldPattern[a] :> ac, 
        HoldPattern[b] :> bc, 
        HoldPattern[root1t] :> root1r, 
				HoldPattern[root2t] :> 
          root2r}\)

form 2

solve (ax^2) + bx + c = 0 for x:

\(root1 = \(\(2\ c\)\/\(\(-b\) + \@\(b\^2 - 4\ a\ c\)\)\ \ \ \ \ \ \ \ \ \ \ \ \ root2 = \(2\ c\)\/\(\(-b\) - \@\(b\^2 - 4\ a\ c\)\)\)\)

root1t = (2*c)/(Sqrt[b*b - (4*a)*c] - b);
root2t = (2*c)/(-Sqrt[b*b - (4*a)*c] - b);

root1r=(twoc\(*\_r\)cc)\(/\_r\)(§[(bc\(*\_r\)bc)\(-\_r\)((fourc\(*\_r\)ac)\(*\_r\)cc)]\(-\_r\)bc);
root2r=(twoc\(*\_r\)cc)\(/\_r\)(Mi[§[(bc\(*\_r\)bc)\(-\_r\)((fourc\(*\_r\)ac)\(*\_r\)cc)]]\(-\_r\)bc);

The reason for the omitted root1 value: root1 had a denominator of zero for two base-two digits.

form 3

solve (ax^2) + bx + c = 0 for x:

\(root1 = \(\(b + sign \((b)\) \@\(b\^2 - 4\ a\ c\)\)\/\(\(-2\) a\)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ root2 = \(\(-2\)\ c\)\/\(b + sign \((b)\) \@\(b\^2 - 4\ a\ c\)\)\)\)

root1t = (b + Sign[b]*Sqrt[b*b - (4*a)*c])/(-2*
              a);
root2t = (-2*c)/(b + 
                Sign[b]*Sqrt[b*b - (4*a)*c]);

root1r=(bc\(+\_r\)(Si[bc]\(*\_r\)§[(bc\(*\_r\)bc)\(-\_r\)((fourc\(*\_r\)ac)\(*\_r\)cc)]))\(/\_r\) Mi[twoc\(*\_r\)ac];
root2r=Mi[twoc\(*\_r\)cc]\(/\_r\)(bc\(+\_r\)(Si[bc]\(*\_r\)§[(bc\(*\_r\)bc)\(-\_r\)((fourc\(*\_r\)ac)\(*\_r\)cc)]));

form 4

solve (ax^2) + bx + c = 0 for x:

\(root1 = \(\(b/2 + sign \((b)\) \@\(\((b/2)\)\^2 - a\ c\)\)\/\(-a\)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ root2 = \ \(-c\)\/\(b/2 + sign \((b)\) \@\(\((b/2)\)\^2 - a\ c\)\)\)\)

root1t = ((b/2) + (Sign[b]*
                  Sqrt[(b/2)*(b/2) - a*c]))/(-a);
root2t = (-c)/((b/2) + (Sign[b]*
                    Sqrt[(b/2)*(b/2) - a*c]));

root1r=((bc\(/\_r\)twoc)\(+\_r\)
	(Si[bc]\(*\_r\)§[((bc\(/\_r\)twoc)\(*\_r\)(bc\(/\_r\)twoc))\(-\_r\)(ac\(*\_r\)cc)]))\(/\_r\)Mi[ac];
root2r=  Mi[cc]\(/\_r\)
	((bc\(/\_r\)twoc)\(+\_r\)(Si[bc]\(*\_r\)§[((bc\(/\_r\)twoc)\(*\_r\)(bc\(/\_r\)twoc))\(-\_r\)(ac\(*\_r\)cc)]));

form 5

solve (ax^2) + bx + c = 0 for x:

ac ≠ 0
({{α={({{\(arg \((\(-b\), 
                                        2 \@ ac)\) ∈ \(\(\((0, π)\)\ \ \ if\ ac\)\(<\)\(0\)\(\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \)\)\)}, {arcsin (-2 (Sqrt[ac])/
                                        b) ∈ [-π/
                                        2, π/2]   if ac > 0}})}, {\(root1 = \(\(\@\(\(|\)\(c/
                                        a\)\(|\)\)\) \(cot\) \((α/
                                    2)\)\(\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \)\)\)}, {\(root2 = \(\(\@\(\(|\)\(c/
                                        a\)\(|\)\)\) \(tan\) \((α/
                                    2)\) \(sign\) \((ac)\)\(\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \)\)\)}})}(b^2)≥4  ac

({{\(α = 
                      arcscos \((\(-b\)/\((2 \@ ac)\))\) ∈ \((0, π/2)\)\)}, {root1 = (Sqrt[|c/a|]) ( 
                          cos (α) + 
                            i sin (α) )     }, {root2 = (Sqrt[|c/a|]) ( 
                          cos (α) - 
                            i sin (α) )     }})}(b^2)<4  ac

\(Notice\ that\ for\ form\ 5\ one\ can\ compute\ complex\ roots\ using\ just\ real\ numbers, and\ I' ll\ demonstrate\) 
	that below.

temp1 = a*c;
temp2 = Sqrt[Abs[c/a]];
\(If[\((b*b)\) ≥ \((4*temp1)\), 
		If[
            temp1 < 0, 
				alpha = 
              ArcTan[\((\(-b\))\), 
                2*\((Sqrt[Abs[temp1]])\)], 
		 (*Else*) 
				alpha = 
              ArcSin[\((2*\((Sqrt[
                          Abs[temp1]])\))\)/\((\(-b\))\)]; 
		 (*EndIf*) ]; 
		temp3 = alpha/2; 
		root1t = 
            temp2*Cot[temp3]; 
		root2t = \((temp2*Tan[temp3])\)*
              Sign[temp1], 
 (*Else*) 
		alpha = 
            ArcCos[\((\(-b\))\)/\((2*\((Sqrt[
                        Abs[temp1]])\))\)]; 
		root1t = {temp2*Cos[alpha], 
              temp2*Sin[alpha]}; 
		root2t = {temp2*Cos[alpha], \(-temp2\)*
                Sin[alpha]}; 
 (*EndIf*) ];\)

tempc1=ac\(*\_r\)cc;
temp2c=§[abs[cc\(/\_r\)ac]];
If[(bc\(*\_r\)bc)≥(fourc\(*\_r\)tempc1),
		If[tempc1<zeroc,
				alphac=arctan2[Mi[bc],twoc\(*\_r\)(§[
                            abs[tempc1]])],
		  
				alphac=arcsin[(twoc\(*\_r\)(§[
                                abs[tempc1]]))\(/\_r\)Mi[bc]];
		  ];
		temp3c=alphac\(/\_r\)twoc;
		root1r=temp2c\(*\_r\)cot[temp3c];
		root2r=(temp2c\(*\_r\)tan[temp3c])\(*\_r\)Si[tempc1],
  
		alphac=arccos[Mi[bc]\(/\_r\)(twoc\(*\_r\)(§[
                          abs[tempc1]]))];
		root1r={temp2c\(*\_r\)cos[alphac],temp2c\(*\_r\)sin[alphac]};
		root2r={temp2c\(*\_r\)cos[alphac],Mi[temp2c\(*\_r\)sin[alphac]]};
  ];

complex number example

{a, b, c} = {17/4, 50/7, 21/4};

GlobalBase = 2;
GlobalDigits = 8;
precis = 20;
ac = NumAllToRDS$R[a];
bc = NumAllToRDS$R[b];
cc = NumAllToRDS$R[c];
twoc = NumAllToRDS$R[2];
fourc = NumAllToRDS$R[4];
zeroc = NumAllToRDS$R[0];

root1r
root1r = Map[RDS$ToRational, root1r]
root1t
SetPrecision[Sqrt[(root1r - root1t) . (root1r - root1t)], 
      precis]

root2r
root2r = Map[RDS$ToRational, root2r]
root2t
SetPrecision[Sqrt[(root2r - root2t) . (root2r - root2t)], 
      precis]

root1: absolute-error for rounding

({{"", 2, 4, 8, 16, 32}, {"form 5", 0.2110761859039024757256234556`12.095070506586964, 0.2889238140960975242743765444`12.21879458078226, 0.0076738140960975242743765444`10.650076103550116, 0.0001054547210975242743765444`8.788322259139976, 7.966713355889047056`3.6665380906962275*^-10}, {"form 4", 0.2110761859039024757256230838`12.195615142804748, 0.2889238140960975242743769162`12.316110969643143, 0.0076738140960975242743769162`10.749182291820727, 0.0001054547210975242743769162`8.887477524444913, 7.966713355889043338`3.7656940401724195*^-10}, {"form 3", 0.2110761859039024757256230837`12.195615142804748, 0.2889238140960975242743769163`12.316110969643143, 0.0076738140960975242743769163`10.749182291820727, 0.0001054547210975242743769163`8.887477524444913, 7.966713355889043337`3.7656940401724195*^-10}, {"form 2", " " 0 denominator, 2.7110761859039024757256054642`12.019448833929175, 0.2110761859039024757256054642`10.906578177284933, 0.0000166155914024757256054642`6.802304674459283, 4.7912641121039843795`3.262238954500086*^-9}, {"form 1", 0.2110761859039024757256230837`12.195615142804748, 0.2889238140960975242743769163`12.316110969643143, 0.0076738140960975242743769163`10.749182291820727, 0.0001054547210975242743769163`8.887477524444913, 7.966713355889043337`3.7656940401724195*^-10}})

root2: absolute-error for rounding

({{"", 2, 4, 8, 16, 32}, {"form 5", 0.0245719622442456724225246926`12.871365117331036, 0.0011344622442456724225246926`11.505953802816098, 0.0001578997442456724225246926`10.64834830553472, 4.101922777650774753074`8.062760644425971*^-7, 3.19951383293902854`3.954857658234488*^-11}, {"form 4", 0.0066780377557543275774752997`12.363432830603312, 0.0011344622442456724225247003`11.605467002125748, 0.0001578997442456724225247003`10.747553824297725, 1.4971563550474225247003`8.724199075050107*^-6, 2.62125225840771295`3.9674384332763815*^-11}, {"form 3", 0.0066780377557543275774752997`12.363432830603312, 0.0011344622442456724225247003`11.605467002125748, 0.0001578997442456724225247003`10.747553824297725, 1.4971563550474225247003`8.724199075050107*^-6, 2.62125225840771295`3.9674384332763815*^-11}, {"form 2", 0.0066780377557543275774752997`12.363432830603312, 0.0011344622442456724225247003`11.605467002125748, 0.0001578997442456724225247003`10.747553824297725, 1.4971563550474225247003`8.724199075050107*^-6, 2.62125225840771295`3.9674384332763815*^-11}, {"form 1", 0.0870719622442456724225250646`12.213220452113525, 0.1629280377557543275774749354`12.465427851092569, 0.0047249127557543275774749354`10.940318706316187, 1.4971563550474225250646`7.441570888118919*^-6, 1.135240139542786047`3.3213913483612254*^-10}})

solve	(ax^2) + bx + c = 0 with a=45/11,    b=211/12,   and c=3/2  
	for a form of the quadratic formula using chopping (base 2)

Clear[§, cos, sin, tan, cot, arccos, arcsin, arctan, 
      arctan2]
§[x_] := RDS$SR$C[x]
cos[x_] := RDS$CosC[x]
sin[x_] := RDS$SinC[x]
tan[x_] := RDS$TanC[x]
cot[x_] := RDS$CotC[x]
arccos[x_] := RDS$ArcCosC[x]
arcsin[x_] := RDS$ArcSinC[x]
arctan[x_] := RDS$ArcTanC[x]
arctan2[x_, y_] := RDS$ArcTan2C[x, y]

{a, b, c} = {45/11, 211/12, 3/2};

GlobalBase = 2;
GlobalDigits = 2;
precis = 10;
ac = NumAllToRDS$C[a];
bc = NumAllToRDS$C[b];
cc = NumAllToRDS$C[c];
twoc = NumAllToRDS$C[2];
fourc = NumAllToRDS$C[4];

form 1

solve (ax^2) + bx + c = 0 for x:

\(root1 = \(\(\(-b\) - \@\(b\^2 - 4\ a\ c\)\)\/\(2\ a\)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ root2 = \(\(-b\) + \@\(b\^2 - 4\ a\ c\)\)\/\(2\ a\)\)\)

form 2

solve (ax^2) + bx + c = 0 for x:

\(root1 = \(\(2\ c\)\/\(\(-b\) + \@\(b\^2 - 4\ a\ c\)\)\ \ \ \ \ \ \ \ \ \ \ \ \ root2 = \(2\ c\)\/\(\(-b\) - \@\(b\^2 - 4\ a\ c\)\)\)\)

form 3

solve (ax^2) + bx + c = 0 for x:

\(root1 = \(\(b + sign \((b)\) \@\(b\^2 - 4\ a\ c\)\)\/\(\(-2\) a\)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ root2 = \(\(-2\)\ c\)\/\(b + sign \((b)\) \@\(b\^2 - 4\ a\ c\)\)\)\)

form 4

solve (ax^2) + bx + c = 0 for x:

\(root1 = \(\(b/2 + sign \((b)\) \@\(\((b/2)\)\^2 - a\ c\)\)\/\(-a\)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ root2 = \ \(-c\)\/\(b/2 + sign \((b)\) \@\(\((b/2)\)\^2 - a\ c\)\)\)\)

form 5

solve (ax^2) + bx + c = 0 for x:

ac ≠ 0
({{α={({{\(arg \((\(-b\), 
                                        2 \@ ac)\) ∈ \(\(\((0, π)\)\ \ \ if\ ac\)\(<\)\(0\)\(\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \)\)\)}, {arcsin (-2 (Sqrt[ac])/
                                        b) ∈ [-π/
                                        2, π/2]   if ac > 0}})}, {\(root1 = \(\(\@\(\(|\)\(c/
                                      a\)\(|\)\)\) \(cot\) \((α/
                                  2)\)\(\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \)\)\)}, {\(root2 = \(\(\@\(\(|\)\(c/
                                      a\)\(|\)\)\) \(tan\) \((α/
                                  2)\) \(sign\) \((ac)\)\(\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \)\)\)}})}(b^2)≥4  ac

({{α = 
                    arcscos (-b/(2 (Sqrt[ ac]))) ∈ (0, π/
                          2)}, {root1 = (Sqrt[|c/a|]) ( 
                        cos (α) + 
                          i sin (α) )     }, {root2 = (Sqrt[|c/a|]) ( 
                        cos (α) - 
                          i sin (α) )     }})}(b^2)<4  ac

root1: absolute-error for chopping

({{"", 2, 4, 8, 16, 32}, {"form 5", 1.2110761859039024757256234556`12.880199272922848, 0.4610761859039024757256234556`12.440854213167865, 0.0389238140960975242743765444`11.354490806105035, 0.0001054547210975242743765444`8.788322259139976, 1.0659738136420523257`3.793005435301965*^-9}, {"form 4", 1.2110761859039024757256230838`12.987892125619618, 0.4610761859039024757256230838`12.543095021902477, 0.0548261859039024757256230838`11.60514894615592, 0.0001386859039024757256230838`9.006451578062235, 2.659316484819861365`4.289184874519184*^-9}, {"form 3", 1.2110761859039024757256230837`12.987892125619618, 0.4610761859039024757256230837`12.543095021902477, 0.0548261859039024757256230837`11.60514894615592, 0.0001386859039024757256230837`9.006451578062235, 2.6593164848198613649`4.289184874519184*^-9}, {"form 2", 3.4610761859039024757256054642`12.126776563643112, 2.7110761859039024757256054642`12.019448833929175, 0.7892011859039024757256054642`11.480287008626487, 0.0029463030914024757256054642`9.051071149395705, 3.99122194694389843705`4.182894722184243*^-8}, {"form 1", 1.2110761859039024757256230837`12.987892125619618, 0.4610761859039024757256230837`12.543095021902477, 0.0548261859039024757256230837`11.60514894615592, 0.0001386859039024757256230837`9.006451578062235, 2.6593164848198613649`4.289184874519184*^-9}})

root2: absolute-error for chopping

({{"", 2, 4, 8, 16, 32}, {"form 5", 0.0245719622442456724225246926`12.871365117331036, 0.0089469622442456724225246926`12.412535010059724, 0.0021110247442456724225246926`11.776857264535243, 5.3118536206724225246926`9.175026263151715*^-6, 8.44201834975445291`4.376219958028467*^-11}, {"form 4", 0.0379280377557543275774752997`13.073184078852023, 0.0066780377557543275774752997`12.363432830603312, 0.0008186627557543275774752997`11.460778067545093, 2.3175409105775774752997`8.91395346251305*^-6, 3.19951383293902777`4.054013607695475*^-11}, {"form 3", 0.0379280377557543275774752997`13.073184078852023, 0.0066780377557543275774752997`12.363432830603312, 0.0008186627557543275774752997`11.460778067545093, 2.3175409105775774752997`8.91395346251305*^-6, 3.19951383293902777`4.054013607695475*^-11}, {"form 2", 0.0379280377557543275774752997`13.073184078852023, 0.0066780377557543275774752997`12.363432830603312, 0.0008186627557543275774752997`11.460778067545093, 2.3175409105775774752997`8.91395346251305*^-6, 3.19951383293902777`4.054013607695475*^-11}, {"form 1", 0.4129280377557543275774749354`12.85026920066049, 0.1629280377557543275774749354`12.465427851092569, 0.0203499127557543275774749354`11.5732374811783, 0.0000595379998949525774749354`9.041093076955185, 8.177985606611999109`4.17894995174136*^-10}})

compare rounding to chopping for each quadratic form and each root (base 2)

Rounding and chopping will only be shown for form 1. This is the best example; the others being
	somewhat redundant or similar.

form 1

root1

({{\(digits \*""""\), "root1 rounded absolute-error", "root1 chopped absolute-error"}, {"2", 0.2110761859039024757256230837`12.195615142804748, 1.2110761859039024757256230837`12.987892125619618}, {"4", 0.2889238140960975242743769163`12.316110969643143, 0.4610761859039024757256230837`12.543095021902477}, {"8", 0.0076738140960975242743769163`10.749182291820727, 0.0548261859039024757256230837`11.60514894615592}, {"16", 0.0001054547210975242743769163`8.887477524444913, 0.0001386859039024757256230837`9.006451578062235}, {"32", 7.966713355889043337`3.7656940401724195*^-10, 2.6593164848198613649`4.289184874519184*^-9}})

root2

({{\(digits \*""""\), "root2 rounded absolute-error", "root2 chopped absolute-error"}, {"2", 0.0870719622442456724225250646`12.213220452113525, 0.4129280377558}, {"4", 0.1629280377557543275774749354`12.465427851092569, 0.1629280377557543275774749354`12.465427851092569}, {"8", 0.0047249127557543275774749354`10.940318706316187, 0.0203499127557543275774749354`11.5732374811783}, {"16", 1.4971563550474225250646`7.441570888118919*^-6, 0.0000595379998949525774749354`9.041093076955185}, {"32", 1.135240139542786047`3.3213913483612254*^-10, 8.177985606611999109`4.17894995174136*^-10}})

Notice that the above emulation results confirm what one expects intuitively for rounding and 
	chopping: for numbers below 5, rounding and chopping are the same, but for numbers 5 and 
	above, rounding is a better estimate than chopping.

form 2

root1

({{\(digits \*""""\), "root1 rounded absolute-error", "root1 chopped absolute-error"}, {"2", \(denominator\ was\ zero \*""""\), 3.4610761859039024757256054642`12.126776563643112}, {"4", 2.7110761859039024757256054642`12.019448833929175, 2.7110761859039024757256054642`12.019448833929175}, {"8", 0.2110761859039024757256054642`10.906578177284933, 0.7892011859039024757256054642`11.480287008626487}, {"16", 0.0000166155914024757256054642`6.802304674459283, 0.0029463030914024757256054642`9.051071149395705}, {"32", 4.7912641121039843795`3.262238954500086*^-9, 3.99122194694389843705`4.182894722184243*^-8}})

root2

({{\(digits \*""""\), "root2 rounded absolute-error", "root2 chopped absolute-error"}, {"2", 0.0066780377557543275774752997`12.363432830603312, 0.0379280377557543275774752997`13.073184078852023}, {"4", 0.0011344622442456724225247003`11.605467002125748, 0.0066780377557543275774752997`12.363432830603312}, {"8", 0.0001578997442456724225247003`10.747553824297725, 0.0008186627557543275774752997`11.460778067545093}, {"16", 1.4971563550474225247003`8.724199075050107*^-6, 2.3175409105775774752997`8.91395346251305*^-6}, {"32", 2.62125225840771295`3.9674384332763815*^-11, 3.19951383293902777`4.054013607695475*^-11}})

form 3

root1

({{\(digits \*""""\), "root1 rounded absolute-error", "root1 chopped absolute-error"}, {"2", 0.2110761859039024757256230837`12.195615142804748, 1.2110761859039024757256230837`12.987892125619618}, {"4", 0.2889238140960975242743769163`12.316110969643143, 0.4610761859039024757256230837`12.543095021902477}, {"8", 0.0076738140960975242743769163`10.749182291820727, 0.0548261859039024757256230837`11.60514894615592}, {"16", 0.0001054547210975242743769163`8.887477524444913, 0.0001386859039024757256230837`9.006451578062235}, {"32", 7.966713355889043337`3.7656940401724195*^-10, 2.6593164848198613649`4.289184874519184*^-9}})

root2

({{\(digits \*""""\), "root2 rounded absolute-error", "root2 chopped absolute-error"}, {"2", 0.0066780377557543275774752997`12.363432830603312, 0.0379280377557543275774752997`13.073184078852023}, {"4", 0.0011344622442456724225247003`11.605467002125748, 0.0066780377557543275774752997`12.363432830603312}, {"8", 0.0001578997442456724225247003`10.747553824297725, 0.0008186627557543275774752997`11.460778067545093}, {"16", 1.4971563550474225247003`8.724199075050107*^-6, 2.3175409105775774752997`8.91395346251305*^-6}, {"32", 2.62125225840771295`3.9674384332763815*^-11, 3.19951383293902777`4.054013607695475*^-11}})

form 4

root1

({{\(digits \*""""\), "root1 rounded absolute-error", "root1 chopped absolute-error"}, {"2", 0.2110761859039024757256230838`12.195615142804748, 1.2110761859039024757256230838`12.987892125619618}, {"4", 0.2889238140960975242743769162`12.316110969643143, 0.4610761859039024757256230838`12.543095021902477}, {"8", 0.0076738140960975242743769162`10.749182291820727, 0.0548261859039024757256230838`11.60514894615592}, {"16", 0.0001054547210975242743769162`8.887477524444913, 0.0001386859039024757256230838`9.006451578062235}, {"32", 7.966713355889043338`3.7656940401724195*^-10, 2.659316484819861365`4.289184874519184*^-9}})

root2

({{\(digits \*""""\), "root2 rounded absolute-error", "root2 chopped absolute-error"}, {"2", 0.0066780377557543275774752997`12.363432830603312, 0.0379280377557543275774752997`13.073184078852023}, {"4", 0.0011344622442456724225247003`11.605467002125748, 0.0066780377557543275774752997`12.363432830603312}, {"8", 0.0001578997442456724225247003`10.747553824297725, 0.0008186627557543275774752997`11.460778067545093}, {"16", 1.4971563550474225247003`8.724199075050107*^-6, 2.3175409105775774752997`8.91395346251305*^-6}, {"32", 2.62125225840771295`3.9674384332763815*^-11, 3.19951383293902777`4.054013607695475*^-11}})

form 5

root1

({{\(digits \*""""\), "root1 rounded absolute-error", "root1 chopped absolute-error"}, {"2", 0.2110761859039024757256234556`12.095070506586964, 1.2110761859039024757256234556`12.880199272922848}, {"4", 0.2889238140960975242743765444`12.21879458078226, 0.4610761859039024757256234556`12.440854213167865}, {"8", 0.0076738140960975242743765444`10.650076103550116, 0.0389238140960975242743765444`11.354490806105035}, {"16", 0.0001054547210975242743765444`8.788322259139976, 0.0001054547210975242743765444`8.788322259139976}, {"32", 7.966713355889047056`3.6665380906962275*^-10, 1.0659738136420523257`3.793005435301965*^-9}})

root2

({{\(digits \*""""\), "root2 rounded absolute-error", "root2 chopped absolute-error"}, {"2", 0.0245719622442456724225246926`12.871365117331036, 0.0245719622442456724225246926`12.871365117331036}, {"4", 0.0011344622442456724225246926`11.505953802816098, 0.0089469622442456724225246926`12.412535010059724}, {"8", 0.0001578997442456724225246926`10.64834830553472, 0.0021110247442456724225246926`11.776857264535243}, {"16", 4.101922777650774753074`8.062760644425971*^-7, 5.3118536206724225246926`9.175026263151715*^-6}, {"32", 3.19951383293902854`3.954857658234488*^-11, 8.44201834975445291`4.376219958028467*^-11}})