changeset 4:b37c218c1442

Initial development of BCD integers
author Paul (paul.d.anderson@comcast.net)
date Thu, 18 Mar 2010 18:10:25 -0700
parents bfda0b347c07
children c021ed211f89
files src/decimal/bcd.d src/decimal/math.d src/decimal/test.d
diffstat 3 files changed, 823 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/decimal/bcd.d	Thu Mar 18 18:10:25 2010 -0700
@@ -0,0 +1,602 @@
+/** 
+ * A D programming language implementation of the 
+ * General Decimal Arithmetic Specification, 
+ * Version 1.70, (25 March 2009).
+ *
+ * by Paul D. Anderson
+ *
+ * Boost Software License - Version 1.0 - August 17th, 2003
+ *
+ * Permission is hereby granted, free of charge, to any person or organization
+ * obtaining a copy of the software and accompanying documentation covered by
+ * this license (the "Software") to use, reproduce, display, distribute,
+ * execute, and transmit the Software, and to prepare derivative works of the
+ * Software, and to permit third-parties to whom the Software is furnished to
+ * do so, all subject to the following:
+ *
+ * The copyright notices in the Software and this entire statement, including
+ * the above license grant, this restriction and the following disclaimer,
+ * must be included in all copies of the Software, in whole or in part, and
+ * all derivative works of the Software, unless such copies or derivative
+ * works are solely in the form of machine-executable object code generated by
+ * a source language processor.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+**/
+
+module decimal.bcd;
+
+import std.conv: ConvError;
+import std.math;
+import std.stdio: write, writeln;
+import std.string: strip;
+
+alias ubyte Digit;
+
+public static immutable Bcd ZERO = { digits:[0] };
+public static immutable Bcd ONE  = { digits:[1] };
+public static immutable Bcd NEG_ONE = { sign:true, digits:[1] };
+
+public struct Bcd {
+
+	// members
+	private bool sign = false;
+	private Digit[] digits = [ 0 ];
+	
+	// constructors
+	public this(const Bcd bcd) {
+		this = bcd;
+	}
+	
+	public this(const Bcd bcd, uint numDigits) {
+		this = bcd;
+		setNumDigits(numDigits);
+	}
+	
+	public this(const string str) {
+		this = str;
+	}
+	
+	public this(const long n) {
+		this = n;
+	}
+		
+	public this(const long n, uint numDigits) {
+		this = n;
+		setNumDigits(numDigits);
+	}
+		
+	const string toString() {
+		return format(this);
+	}
+	
+	const hash_t toHash() {
+		hash_t hash = 0;
+		foreach(Digit digit; digits) {
+			hash += digit;
+		}
+		return hash;
+	}
+	
+	// access methods	
+	const uint numDigits() {
+		return digits.length;
+	}
+	
+	void setNumDigits(uint n) {
+		digits.length = n;
+	}
+	
+	const uint firstDigit() {
+		return digits[$-1];
+	}
+	
+	const uint lastDigit() {
+		return digits[0];
+	}
+	
+	void setDigit(uint n, Digit value) {
+		digits[$-n-1] = value;
+	}
+	
+	const int getDigit(int n) {
+		return digits[$-n-1];
+	}
+	
+	unittest {
+		write("digits...");
+		Bcd bcd = Bcd(12345678L);
+		assert(bcd.numDigits() == 8);
+		assert(bcd.firstDigit() == 1);
+		assert(bcd.lastDigit() == 8);
+		assert(bcd.getDigit(3) == 4);
+		bcd.setDigit(3, 7);
+		assert(bcd.getDigit(3) == 7);
+		bcd.setNumDigits(10);
+		assert(bcd.numDigits == 10);
+		assert(bcd.firstDigit() == 0);
+		assert(bcd.getDigit(5) == 7);
+		bcd.setNumDigits(5);
+		assert(bcd.getDigit(2) == 6);
+//		writeln("bcd = ", bcd);
+		writeln("passed!");
+	}
+	
+	const bool isSigned() {
+		return sign;
+	}
+	
+	const bool isZero() {
+		writeln("stripping");
+		Bcd temp = stripLeadingZeros(this);
+		writeln("stripped");
+		writeln("temp = ", temp);
+		if (temp.numDigits > 1) return false;
+		return temp.lastDigit == 0;
+	}
+	
+	const bool hasLeadingZeros() {
+		return numDigits > 0 && firstDigit == 0;
+	}
+	
+	void opAssign(const Bcd that) {
+		this.sign = that.sign;
+		this.digits.length = that.digits.length;
+		this.digits[] = that.digits[];
+	}
+	
+	void opAssign(const string str) {
+		this = parse(str);
+	}
+	
+	void opAssign(const long n) {
+		uint m;	
+		if (n < 0) {
+			sign = true;
+			m = std.math.abs(n);
+		}
+		else {
+			sign = false;
+			m = n;
+		}
+		Digit[20] dig;
+		int i = 0;
+		do {
+			uint q = m/10;
+			uint r = m%10;
+			dig[i] = cast(Digit) r;
+			m = q;
+			i++;
+		} while (m > 0);
+		digits = dig[0..i].dup;
+	}
+	
+	
+	// index operator
+	Digit opIndex(uint index) {
+		return this.digits[index];
+	}
+	
+	// index assign operator
+	void opIndexAssign(Digit value, uint index) {
+		this.digits[index] = value;
+	}
+	
+/+	int opApply(int delegate (ref Digit) dg) {
+		int result = 0;
+		for (int i = 0; i < numDigits; i++) {
+			result = dg(digits[i]);
+			if (result) break;
+		}
+		return result;
+	}
+	
+	int opApply(int delegate (ref Digit) dg) {
+		int result = 0;
+		for (int i = 0; i < numDigits; i++) {
+			result = dg(digits[i]);
+			if (result) break;
+		}
+		return result;
+	}
+	
+	int opApplyReverse(int delegate (ref Digit) dg) {
+		int result = 0;
+		for (int i = 0; i < numDigits; i++) {
+			result = dg(digits[i]);
+			if (result) break;
+		}
+		return result;
+	}+/
+	
+	const Bcd dup() {
+		Bcd bcd;
+		bcd.sign = this.sign;
+		bcd.digits.length = this.digits.length;
+		bcd.digits[] = this.digits[];
+		return bcd;
+	}
+	
+	// TODO: always uncertain how this is done...will it make an unnecessary copy?
+	const Bcd opPos() {
+		return this.dup;
+	}
+	
+	const Bcd opNeg() {
+		return negate(this);
+	}
+	
+	const Bcd opCom() {
+		return complement(this);
+	}
+	
+	const Bcd opNot() {
+		return not(this);
+	}
+	
+	const Bcd opAnd(const Bcd bcd) {
+		return and(this, bcd);
+	}
+	
+	const Bcd opOr(const Bcd bcd) {
+		return or(this, bcd);
+	}
+	
+	const Bcd opXor(const Bcd bcd) {
+		return xor(this, bcd);
+	}
+	
+	// TODO: what's the matter with the one-digit numbers??
+	const bool opEquals(T:Bcd)(const T that) {
+//		writeln("equating");
+		if (this.sign != that.sign) return false; 	// what about +/- zero?
+//		writeln("same signs");
+		Bcd thisOne = stripLeadingZeros(this);
+//		writeln("this = ", thisOne);
+		Bcd thatOne = stripLeadingZeros(that);
+//		writeln("that = ", thatOne);
+		if (thisOne.digits.length != thatOne.digits.length) return false;
+//		writeln("length = ", thisOne.digits.length);
+//		foreach(int i, Digit digit; thisOne) {	// todo: have to make opApply here.
+//		}
+		foreach_reverse(int i, Digit digit; thisOne.digits) {
+/+			writeln("i = ", i);
+			writeln("this[i] = ", thisOne.digits[i]);
+			writeln("that[i] = ", thatOne.digits[i]);
+			writeln("this = ", thisOne.digits);
+			writeln("that = ", thatOne.digits);+/
+			if (digit != thatOne.digits[i]) return false;
+		}
+		return true;
+	}
+	
+	const bool opEquals(T)(const T that) {
+		return opEquals(Bcd(that));
+	}
+	
+} // end struct Bcd
+
+private bool isDigit(const char ch) {
+	return (ch >= '0' && ch <= '9');
+}
+
+public string format(const Bcd bcd, bool showPlus = false, bool showLeadingZeros = false) {
+	int len = bcd.digits.length;
+	if (bcd.sign) len++;
+	char[] str = new char[len];
+	
+	int index = 0;
+	if (bcd.sign) {
+		str[index] = '-';
+		index++;
+	}
+	
+	foreach_reverse(Digit digit; bcd.digits) {
+		str[index] = cast(char) digit + '0';
+		index++;
+	}
+	return str.idup;
+}
+
+public Bcd parse(string str) {
+	Bcd bcd;
+	// are leading zeros retained?
+	bool lz = false;
+
+	// strip whitespace, convert to char array
+	char[] str1 = str.strip.dup;
+	
+	// check for leading '-'
+	if (str1[0] == '-') {
+		bcd.sign = true;
+		str1 = str1[1..$];
+		lz = true;
+	}
+	
+	// check for leading '+'
+	if (str1[0] == '+') {
+		bcd.sign = false;
+		str1 = str1[1..$];
+		lz = true;
+	}
+	
+	// verify chars are digits, strip out underscores
+	int index = 0;
+	char[] str2 = new char[str1.length];
+	foreach_reverse(char ch; str1) {
+		if (isDigit(ch)) {
+			str2[index] = ch;
+			index++;
+			continue;
+	    }
+		if (ch == '_') {
+			continue;
+		}
+		throw (new ConvError("Invalid character: " ~ ch));
+	}
+	str2.length = index;
+	
+	bcd.digits.length = index;
+	foreach(int i, char ch; str2) {
+		bcd.digits[i] = cast(Digit)(ch - '0');
+	}
+
+	if (!lz)  return stripLeadingZeros(bcd);	
+	return bcd;
+}
+
+public Bcd copy(const Bcd bcd) {
+	return bcd.dup;
+}
+
+public Bcd negate(const Bcd bcd) {
+	Bcd copy = bcd; //.dup;
+	copy.sign = !bcd.sign;
+	return copy;
+}
+
+public Bcd abs(const Bcd bcd) {
+	return bcd.isSigned ? -bcd: +bcd;
+}
+
+public Bcd stripLeadingZeros(const Bcd bcd) {
+	Bcd result = bcd.dup;
+	if (!bcd.hasLeadingZeros) return result;
+	int len = bcd.numDigits;
+	int i = 0;
+	while(i < len-1 && bcd.getDigit(i) == 0) {
+		i++;
+	} 
+	result.setNumDigits(len - i);
+	return result;
+}
+
+
+unittest {
+	write("strip...");
+	Bcd bcd;
+	bcd = "+00123";
+	assert(bcd.toString == "00123");
+	bcd = stripLeadingZeros(bcd);
+	writeln("bcd = ", bcd);
+	assert(bcd.toString == "123");
+	bcd = "+000";
+	writeln("bcd = ", bcd);
+	assert(bcd.toString == "000");
+	bcd = stripLeadingZeros(bcd);
+	writeln("bcd = ", bcd);
+	writeln("passed");
+}
+	
+public bool sameLength(const Bcd a, const Bcd b) {
+	return a.numDigits == b.numDigits;
+}
+
+public int setSameLength(ref Bcd a, ref Bcd b) {
+	if (sameLength(a,b)) return a.numDigits;
+	uint alen = a.numDigits;
+	uint blen = b.numDigits;
+	if (alen > blen) {
+		b.setNumDigits(alen);
+	}
+	else {
+		a.setNumDigits(blen);
+	}
+	return a.numDigits();
+}
+
+public Bcd complement(const Bcd a) {
+	Bcd b = Bcd(0, a.numDigits);
+	foreach(int i, Digit digit; a.digits) {
+		b.digits[i] = digit == 0 ? 1 : 0 ;
+	}
+	return b;
+}
+
+unittest {
+	write("com...");
+	Bcd bcd;
+	bcd = 123;
+	assert(complement(bcd).toString == "000");
+	bcd = 40509;
+	assert(complement(bcd).toString == "01010");
+//	writeln("bcd = ", bcd);
+//	writeln("~bcd = ", complement(bcd));
+	writeln("passed");
+}
+	
+public int sgn(Bcd bcd) {
+	if (bcd.isZero) return 0;
+	return bcd.isSigned ? -1 : 1;
+}
+
+public Bcd not(const Bcd x) {
+	Bcd result = x.dup;
+	for (int i = 0; i < x.numDigits; i++) {
+		result[i] = not(result[i]);
+	}
+	return result;
+}
+
+private Digit not(const Digit a) {
+	return a != 0;
+}
+
+public Bcd and(const Bcd x, const Bcd y) {
+	Bcd a = x.dup;
+	Bcd b = y.dup;
+	int len = setSameLength(a,b);
+	Bcd result = Bcd(0, len);
+	for (int i = 0; i < len; i++) {
+		result[i] = and(a[i], b[i]);
+	}
+	return result;
+}
+
+private Digit and(const Digit a, const Digit b) {
+	return a != 0 && b != 0;
+}
+
+unittest {
+	write("and...");
+	Bcd a;
+	Bcd b;
+	a = 123000;
+	b = 123000;
+	assert(and(a,b).toString == "111000");
+	b = 12300;
+	assert(and(a,b).toString == "011000");
+	a = 1234567;
+	b = 7654321;
+	assert(and(a,b).toString == "1111111");
+	a = 1010;
+	b = 101;
+	writeln("a = ", a);
+	writeln("b = ", b);
+	writeln("and = ", and(a,b));
+	assert(and(a,b).isZero);
+	writeln("passed!");
+}
+
+// TODO: looks like there's some room for templates or mixins here.
+public Bcd or(const Bcd x, const Bcd y) {
+	Bcd a = x.dup;
+	Bcd b = y.dup;
+	int len = setSameLength(a,b);
+	Bcd result = Bcd(0, len);
+	for (int i = 0; i < len; i++) {
+		result[i] = or(a[i], b[i]);
+	}
+	return result;
+}
+
+private Digit or(const Digit a, const Digit b) {
+	return a != 0 || b != 0;
+}
+
+
+public Bcd xor(const Bcd x, const Bcd y) {
+	Bcd a = x.dup;
+	Bcd b = y.dup;
+	int len = setSameLength(a,b);
+	Bcd result = Bcd(0, len);
+	for (int i = 0; i < len; i++) {
+		result[i] = xor(a[i], b[i]);
+	}
+	return result;
+}
+
+private Digit xor(const Digit a, const Digit b) {
+	return (a == 0 && b != 0) || (a != 0 && b == 0);
+}
+
+public Bcd add(const Bcd a, const Bcd b) {
+	Bcd x = a.dup;
+	Bcd y = b.dup;
+	int len = setSameLength(x, y);
+	Bcd result = Bcd(0, len+1);
+	Digit carry = 0;
+	uint i;
+	for (i = 0; i < len; i++) {
+		result[i] = add(x[i], y[i], carry);
+	}
+	if (carry) {
+		result[i] = 1;
+	}
+	else {
+		result = stripLeadingZeros(result);
+	}
+	return result;
+}
+
+private Digit add(const Digit a, const Digit b, ref Digit carry) {
+	Digit sum = a + b + carry;
+	if (sum > 9) {
+		sum -= 10;
+		carry = 1;
+	}
+	else {
+		carry = 0;
+	}
+	return sum;
+}
+
+unittest {
+	write("add...");
+	Bcd a, b;
+	a = 123;
+	b = 222;
+	Bcd sum = add(a,b);
+	assert(sum == 345);
+	a = 2;
+	b = 102000;
+	sum = add(a,b);
+	assert(sum == 102002);
+	writeln("passed!");
+}
+
+//==========================================
+
+public void main() {
+	writeln("Hello, world");
+	Bcd bcd;
+	writeln("bcd = ", format(bcd));
+	bcd = parse("12");
+	writeln("bcd = ", format(bcd));
+	bcd = parse("012");
+	writeln("bcd = ", format(bcd));
+	bcd = parse("-012");
+	writeln("bcd = ", format(bcd));
+	bcd = parse("+012");
+	writeln("bcd = ", format(bcd));
+	bcd = parse("-0");
+	writeln("bcd = ", format(bcd));
+	bcd = parse("012_345_678");
+	writeln("bcd = ", format(bcd));
+
+	bcd = 1234;
+	writeln("bcd = ", format(bcd));
+	bcd = 12345678L;
+	writeln("bcd = ", format(bcd));
+	writeln("a == b : ", Bcd(0) == Bcd(0));
+	writeln("a == b : ", Bcd(4) == Bcd(4));
+	writeln("a == b : ", Bcd(40) == Bcd(40));
+	writeln("a == b : ", Bcd(-400) == Bcd(-400));
+	writeln("a == b : ", Bcd(12345678) == Bcd(+12345678));
+	writeln("a != b : ", Bcd(40) == Bcd(53));
+	writeln("a != b : ", Bcd(402) == Bcd(531));
+	writeln("a != b : ", Bcd(402) == Bcd(-402));
+    writeln("a != b : ", Bcd(65432) == Bcd(65431));
+	writeln("a != b : ", Bcd(2) == Bcd(1));
+	writeln("a != b : ", Bcd(1) == Bcd(2));
+	writeln("OK!");
+}
+
+
+
--- a/src/decimal/math.d	Thu Mar 18 18:09:20 2010 -0700
+++ b/src/decimal/math.d	Thu Mar 18 18:10:25 2010 -0700
@@ -34,6 +34,7 @@
 
 import decimal.decimal;
 import decimal.context;
+//import std.math;
 
 public:
     
@@ -42,6 +43,14 @@
     // CONSTANTS
     //
     //--------------------------------
+	
+/+	public Decimal HALF;
+	public Decimal ONE = Decimal(1);
+	public Decimal ZERO = Decimal(0);
+	
+	static {
+		HALF = Decimal("0.5");
+	}+/
 
     /**
      * Returns the value of e to the default precision.
@@ -59,14 +68,62 @@
         return result;
     }
      
+/+
     /**
      * Returns the value of pi to the default precision.
      */    
     Decimal pi() {
-        Decimal result;
-        return result;
+		Decimal ONE = Decimal(1);
+		writeln("1 = ", ONE);
+		Decimal TWO = Decimal(2);
+		writeln("2 = ", TWO);
+		Decimal HALF = Decimal(0.5);
+		writeln("0.5 = ", HALF);
+        Decimal x = sqrt(TWO);
+		writeln("x = ", x);
+		Decimal y = sqrt(x);
+		writeln("y = ", y);
+		Decimal p = TWO + x;
+		writeln("p = ", p);
+		x = y;
+		int i = 0;
+		while (true) {
+			writeln("i = ", i);
+			x = HALF * (x + ONE/x);
+			writeln("step 1");
+			Decimal np = p * ((x + ONE)/(y + ONE));
+			writeln("step 2");
+			writeln("np = ", np);
+			if (p == np) return p;
+			writeln("step 3");
+			p = np;
+			writeln("step 4");
+			x = sqrt(x);
+			writeln("step 5");
+//			writeln("x = ", x);
+			Decimal oox = ONE/x;
+//			writeln("ONE/x = ", oox);
+//			writeln ("x + ONE/x = ", x + oox);
+//			Decimal t1 = oox + x;
+//			writeln("t1 = ", t1);
+//			Decimal t1 = x + oox; // ONE + oox; //x + x; // + ONE/x;
+			writeln("step 6");
+//			Decimal t2 = (y  * x) + ONE; ///x; //ONE / (y + ONE);
+//			y = ONE/x + y * x;
+			writeln("step 7");
+			y = (ONE/x + y * x) / (y + ONE); //t1 / t2;
+			writeln("step 8");
+			i++;
+//			break;
+		}
+        return p;
     }
-     
+	
+	unittest {
+		write("pi....");
+		writeln("pi = ", pi());
+	}
++/     
     /**
      * Returns the value of pi to the specified precision.
      */    
@@ -76,19 +133,38 @@
     }
      
     /**
-     * Returns the square root of the argument to the default precision.
+     * Returns the square root of the argument to the current precision.
      */    
     Decimal sqrt(Decimal arg) {
-        Decimal result;
-        return result;
+		return sqrt(arg, context.precision);
     }
+	
+	
+	unittest {
+		write("sqrt.....");
+		Decimal dcm = Decimal(4);
+		assert(sqrt(dcm) == Decimal(2));
+		writeln("sqrt(2) = ", sqrt(Decimal(2)));
+	}
      
     /**
      * Returns the square root of the argument to the specified precision.
      */    
     Decimal sqrt(Decimal arg, uint precision) {
-        Decimal result;
-        return result;
+		pushContext();
+		context.precision = precision + 2;
+		Decimal HALF = Decimal(0.5);
+		Decimal ONE = Decimal(1);
+		Decimal x = HALF * (arg + ONE);
+		Decimal xp;
+		while(true){
+			xp = x;
+			x = HALF * (x + arg/x);
+			if (x == xp) break;
+		}
+		popContext();
+		round(xp);
+        return xp;
     }
     
     //--------------------------------
@@ -312,7 +388,7 @@
         return result;
     }
 
-    //--------------------------------
+/+    //--------------------------------
     //
     // General Decimal Arithmetic Specification Functions
     //
@@ -553,6 +629,6 @@
         Decimal result;
         return result;
     }
++/
 
 
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/decimal/test.d	Thu Mar 18 18:10:25 2010 -0700
@@ -0,0 +1,135 @@
+/** 
+ * A D programming language implementation of the 
+ * General Decimal Arithmetic Specification, 
+ * Version 1.70, (25 March 2009).
+ *
+ * by Paul D. Anderson
+ *
+ * Boost Software License - Version 1.0 - August 17th, 2003
+ *
+ * Permission is hereby granted, free of charge, to any person or organization
+ * obtaining a copy of the software and accompanying documentation covered by
+ * this license (the "Software") to use, reproduce, display, distribute,
+ * execute, and transmit the Software, and to prepare derivative works of the
+ * Software, and to permit third-parties to whom the Software is furnished to
+ * do so, all subject to the following:
+ *
+ * The copyright notices in the Software and this entire statement, including
+ * the above license grant, this restriction and the following disclaimer,
+ * must be included in all copies of the Software, in whole or in part, and
+ * all derivative works of the Software, unless such copies or derivative
+ * works are solely in the form of machine-executable object code generated by
+ * a source language processor.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+**/
+module decimal.test;
+
+import decimal.decimal;
+import decimal.math;
+
+public void main2() {
+		Decimal ONE = Decimal(1);
+		writeln("1 = ", ONE);
+		Decimal TWO = Decimal(2);
+		writeln("2 = ", TWO);
+		Decimal HALF = Decimal(0.5);
+		writeln("0.5 = ", HALF);
+        Decimal x = sqrt(TWO);
+		writeln("x = ", x);
+		Decimal y = sqrt(x);
+		writeln("y = ", y);
+		Decimal p = TWO + x;
+		writeln("p = ", p);
+		x = y;
+		int i = 0;
+		while (true) {
+			writeln("i = ", i);
+			x = x + ONE/x;
+			writeln("step 0");
+//			x = HALF (x + ONE/x);
+			x *= HALF;
+			writeln("step 1");
+			Decimal np = p * ((x + ONE)/(y + ONE));
+			writeln("step 2");
+			writeln("np = ", np);
+			if (p == np) return p;
+			writeln("step 3");
+			p = np;
+			writeln("step 4");
+			x = sqrt(x);
+			writeln("step 5");
+//			writeln("x = ", x);
+			Decimal oox = ONE/x;
+//			writeln("ONE/x = ", oox);
+//			writeln ("x + ONE/x = ", x + oox);
+//			Decimal t1 = oox + x;
+//			writeln("t1 = ", t1);
+//			Decimal t1 = x + oox; // ONE + oox; //x + x; // + ONE/x;
+			writeln("step 6");
+//			Decimal t2 = (y  * x) + ONE; ///x; //ONE / (y + ONE);
+//			y = ONE/x + y * x;
+			writeln("step 7");
+			y = (ONE/x + y * x) / (y + ONE); //t1 / t2;
+			writeln("step 8");
+			i++;
+//			break;
+			writeln("i = ", i);
+			
+		}
+        return p;
+}
+
+public void main() {
+	writeln("Hello, world!");
+/+	writeln("eTiny = ", context.eTiny);
+	writeln("tiny min = ", Decimal(1, context.eTiny));
+	writeln("tiny min = ", Decimal(1, context.eTiny - 1));
+	writeln("max = ", context.max());
+	writeln("max1 = ", Decimal(999999999, 99));
+	writeln("dig = ", context.dig());
+	writeln("eps = ", context.epsilon());
+	writeln("smallest = ", context.min_normal()*context.epsilon());
+	writeln("1/epsilon = ", Decimal(1)/context.epsilon());
+	writeln("max * min = ", context.max * context.min_normal);
+	writeln("mant_dig = ", context.mant_dig);
+	writeln("min_exp = ", context.min_exp);
+	writeln("max_exp = ", context.max_exp);+/
+	
+	
+    // TODO: this next one goes crazy -- shows need for checks on construction
+	// TODO: turns out this is being converted to a double (or real) and
+	// then it's really weird.
+//	writeln("bigger = ", Decimal(999999999999));
+//	float f = float.max;
+	// TODO: convert these to assserts
+/+	writeln("f.max = ", f);
+	writeln("f.min = ", float.min);
+	writeln("f = ", 2 * float.min);
+	writeln("d.max = ", Decimal.max());
+	writeln("d.min = ", Decimal.min_normal());
+	writeln("2 * d.min = ", 2 * Decimal.min_normal());
+	writeln("0.1 * d.min = ", 0.1 * Decimal.min_normal());+/
+	// TODO: move this to unittesting
+/+	Decimal dec = Decimal(PI);
+	writeln("pi = ", dec );
+	dec = Decimal(PI, 19);
+	writeln("pi = ", dec );
+	dec = Decimal(1.3, 25);
+	writeln("pi = ", dec );
+	dec = Decimal(0.1, 25);
+	writeln("pi = ", dec );
+	dec = Decimal(2.0, 25);
+	writeln("pi = ", dec );
+	dec = Decimal(200.5, 25);
+	writeln("pi = ", dec );
+	writeln(double.dig);
+	writeln(real.dig);+/
+}
+