summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Boehm <hboehm@google.com>2014-11-26 13:35:59 -0800
committerHans Boehm <hboehm@google.com>2014-11-26 13:50:15 -0800
commit36dc537535bd06a87d652c9d3c369e1f748aa45b (patch)
tree8c5311aa256ae53e60b1158fb94101087dbc1e1d
parent349dbd732e48cf93b11291291e056fc5a3829f31 (diff)
downloadcrcalc-36dc537535bd06a87d652c9d3c369e1f748aa45b.tar.gz
Cleanup in preparation for Android use.
- Remove files we do not expect to use. We want only the arithmetic package, not the old calculator applet UI, nor the simple comand-line one. - Adjust white space in remaining files. - Remove the part of COPYRIGHT.txt that applied only to a now deleted file. No substantive changes except for file deletions. Change-Id: Ife71985023ac60adc10caf016ada704ad08d19d6
-rw-r--r--COPYRIGHT.txt22
-rw-r--r--CRCalc-force.html79
-rw-r--r--CRCalc.html163
-rw-r--r--Makefile55
-rw-r--r--instrs.html285
-rw-r--r--src/AbortedError.java12
-rw-r--r--src/CR.java1152
-rw-r--r--src/CRCalc.java1605
-rw-r--r--src/PrecisionOverflowError.java12
-rw-r--r--src/UnaryCRFunction.java778
-rw-r--r--src/rpn_calc.java262
-rw-r--r--tests/TestCR.java164
12 files changed, 1062 insertions, 3527 deletions
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 7a92f8a..8ea1575 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -1,7 +1,6 @@
-The following license covers all material included in the CRCalc.tar
-file, except rpn_calc.java:
+The following license covers all material remaining in this directory.
-Copyright © 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED
+Copyright © 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED
Permission is granted free of charge to copy, modify, use and distribute
this software provided you include the entirety of this notice in all
@@ -37,20 +36,5 @@ between California residents. Any litigation relating to these license
terms shall be subject to the exclusive jurisdiction of the Federal Courts
of the Northern District of California (or, absent subject matter
jurisdiction in such courts, the courts of the State of California), with
-venue lying exclusively in Santa Clara County, California.
-
-The following license covers rpn_calc.java:
-
-Copyright (c) 2001 Hewlett-Packard Company
-
-Permission to use, copy, modify, distribute and sell this software
-and its documentation for any purpose is hereby granted without fee,
-provided that the above copyright notice appear in all copies and
-that both that copyright notice and this permission notice appear
-in supporting documentation.
-HEWLETT-PACKARD COMPANY MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY
-OF THIS SOFTWARE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT
-EXPRESS OR IMPLIED WARRANTY.
-
-
+venue lying exclusively in Santa Clara County, California.
diff --git a/CRCalc-force.html b/CRCalc-force.html
deleted file mode 100644
index 8eb1adb..0000000
--- a/CRCalc-force.html
+++ /dev/null
@@ -1,79 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>Constructive Reals Calculator</title>
-</head>
-<BODY BGCOLOR="#FFFFFF">
-<H1>
-Constructive Reals Calculator
-</h1>
-This is a slightly modified version of the constructive reals calculator
-developed by Hans-J. Boehm at SGI. The copyright belongs to SGI.
-Since it appears to no longer be available on the SGI site, it was rehosted
-here, as allowed by its <A HREF="COPYRIGHT.txt">license</a>.
-<P>
-<APPLET code=CRCalc.class width=500 height=570
-ALT="Calculator requires Java 1.1">
-<PARAM NAME="rows" VALUE="6">
-</applet>
-</center>
-<P>
-This fallback version uses the default font, unarchived class files, and does
-not attempt to identify the browser. It is tailored for smaller displays.
-<H2>Overview</h2>
-This is a calculator that operates on constructive real numbers.
-Numbers are represented exactly internally to the calculator, and then
-evaluated on demand to guarantee an error in the displayed result that
-is strictly less than one in the least significant displayed digit.
-It is possible to scroll the display to the right to generate
-essentially arbitrary precision in the result.
-<P>
-The calculator uses reverse Polish notation. To add 1 and 2, either
-click &lt;1&gt;&lt;enter&gt;&lt;2&gt;&lt;+&gt; on the calculator keypad,
-or click on the
-display, so that it receives keyboard input, and type 1&lt;space&gt;2+
-on the keyboard. For more detailed instructions, click
-<A HREF="instrs.html">here</a>.
-<H2>Examples</h2>
-Try e<SUP>PI &#183; sqrt(163)</sup>,
-entered as 163 &lt;sqrt&gt; &lt;pi&gt; &lt;*&gt; &lt;exp&gt; .
-<P>
-To demonstrate the effect of demand-driven evaluation, try
-<P>
-123 &lt;+/-&gt; &lt;exp&gt; &lt;pi&gt; &lt;+&gt; &lt;ln&gt; &lt;exp&gt;
-&lt;pi&gt; &lt;-&gt; &lt;ln&gt;.
-<P>
-or
-<P>
-10 &lt;enter&gt; 25 &lt;^&gt; &lt;atan&gt; &lt;tan&gt;
-<H2>Library Interface</h1>
-The calculator is implemented on top of a Java library that implements
-constructive real arithmetic.
-The library will live in com.sgi.Math.
-It provides two interesting classes:
-<P>
-<A HREF="CR.java">CR</a> provides constructive reals as a subclass
-of <TT>Number</tt>. Its interface is described
-<A HREF="com/sgi/math/CR.html">here</a>.
-<P>
-<A HREF="UnaryCRFunction.java">UnaryCRFunction</a>
-provides some limited operations
-on unary functions over the constructive reals. It also provides a large
-number of constants for commonly used functions.
-Its interface is described
-<A HREF="com/sgi/math/UnaryCRFunction.html">here</a>.
-<P>
-Some general information on the implementation is <A HREF="impl.html">here</a>.
-<P>
-The entire calculator can be downloaded as a compressed tar file
-<A HREF="download/CRCalc.tar.gz">here</a>.
-<H2>Copyright</h2>
-The calculator and library code are copyrighted by Silicon Graphics, Inc.
-They may be used and redistributed subject to conditions specified
-<A HREF="COPYRIGHT.txt">here</a> and in the source files.
-<H2>Contact</h2>
-Please send comments or questions to
-<A HREF="mailto:Hans_Boehm@hp.com">Hans_Boehm@hp.com</a>.
-<A HREF="../index.html">Hans Boehm's home page</a>.
-</center>
-</body>
-</html>
diff --git a/CRCalc.html b/CRCalc.html
deleted file mode 100644
index 1ed82e5..0000000
--- a/CRCalc.html
+++ /dev/null
@@ -1,163 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>Constructive Reals Calculator</title>
-</head>
-<BODY BGCOLOR="#FFFFFF">
-<H1>
-Constructive Reals Calculator
-</h1>
-This is a slightly modified version of the constructive reals calculator
-developed by Hans-J. Boehm at SGI. The copyright belongs to SGI.
-Since it appears to no longer be available on the SGI site, it was rehosted
-here, as allowed by its <A HREF="COPYRIGHT.txt">license</a>.
-<P>
-<NOSCRIPT>
-Your browser does not support JavaScript, or it has been disabled.
-Hence we cannot determine
-the identity of the browser. You will need a browser with support for
-at least Java 1.1 to correctly run the calculator Applet.
-Netscape 4 or Internet Explorer version 4 or later should suffice.
-To try to run the applet anyway, click
-<A HREF="CRCalc-force.html">here</a>.
-</noscript>
-<SCRIPT language="javascript">
-<!---
- var navVersion = navigator.appVersion;
- var navName = navigator.appName;
- var goodBrowser = false;
- var badBrowser = false;
- document.open();
- if (navName=="Netscape") {
- if (navVersion >= "4.00") {
- goodBrowser = true;
- } else {
- badBrowser = true;
- }
- }
- if (navName=="Microsoft Internet Explorer") {
- if (navVersion >= "4.0") {
- goodBrowser = true;
- } else {
- badBrowser = true;
- }
- }
- if (!goodBrowser) {
- if (!badBrowser) {
- document.write("Your " + navName + " web browser is not recognized. "
- + "The following applet requires at least Java 1.1 support. "
- + "If it does not function correctly, please upgrade your "
- + "browser, enable Java, or see <A HREF='download.html'>here</a> "
- + "for instructions on how to run it outside yout browser.");
- document.write("<CENTER><APPLET code=CRCalc.class archive='classes.jar' "
- + "width=500 height=570 ALT='Failed to start Java applet'> </applet>"
- + "</center>");
- } else {
- document.write(
- "The calculator applet requires at least Java 1.1 support. "
- + "You are running version " + navVersion + " of "
- + navName + ". "
- + "Please upgrade your browser to version 4 or later, "
- + "or see <A HREF='download.html'>here</a> "
- + "for instructions on how to run it outside your browser.");
- }
- } else {
- if (navigator.javaEnabled()) {
- document.write("<CENTER><APPLET code=CRCalc.class archive='classes.jar' "
- + "width=500 height=570 ALT='Failed to start Java applet'>");
- // Navigator tends to do a much better job with the Dialog font
- // than Courier. For some other browsers, Dialog has variable
- // width.
- if (navName == "Netscape") {
- var os_name = navigator.platform.substr(0,3).toLowerCase();
- if (os_name == "lin" || os_name == "iri") {
- document.write("<PARAM NAME='font' VALUE='Dialog'>");
- }
- if (os_name == "lin" || os_name == "sol") {
- // Netscape seems to get TextArea sizes right on Linux
- // and probably Solaris. Thus we can leave off the extra
- // padding on those.
- document.write("<PARAM NAME='extra_rows' VALUE='0'>");
- document.write("<PARAM NAME='extra_columns' VALUE='0'>");
- }
- } else {
- // IE4 seems to get confused with no extra padding once
- // the vertical scrollbar appears.
- // It seems to do better with default padding.
- }
- document.write("</applet></center>");
- } else {
- document.write("Your browser supports Java, but it is disabled. "
- + "You will need to enable it to run the calculator applet. ");
- if (navName == "Netscape") {
- document.write("To enable java, try Edit->preferences->advanced. ");
- }
- }
- }
- document.write(
- "<P> Click <A HREF='CRCalc-force.html'>here</a> to force your "
- + "browser to try to run the calculator in default mode "
- + "without browser testing. This may help if your "
- + "browser is misidentified, complains that it can't "
- + "find classes, or otherwise fails to run the above "
- + "applet correctly.");
- document.close();
-// -->
-</script>
-<H2>Overview</h2>
-This is a calculator that operates on constructive real numbers.
-Numbers are represented exactly internally to the calculator, and then
-evaluated on demand to guarantee an error in the displayed result that
-is strictly less than one in the least significant displayed digit.
-It is possible to scroll the display to the right to generate
-essentially arbitrary precision in the result.
-<P>
-The calculator uses reverse Polish notation. To add 1 and 2, either
-click &lt;1&gt;&lt;enter&gt;&lt;2&gt;&lt;+&gt; on the calculator keypad,
-or click on the
-display, so that it receives keyboard input, and type 1&lt;space&gt;2+
-on the keyboard. For more detailed instructions, click
-<A HREF="instrs.html">here</a>.
-<H2>Examples</h2>
-Try e<SUP>PI &#183; sqrt(163)</sup>,
-entered as 163 &lt;sqrt&gt; &lt;pi&gt; &lt;*&gt; &lt;exp&gt; .
-<P>
-To demonstrate the effect of demand-driven evaluation, try
-<P>
-123 &lt;+/-&gt; &lt;exp&gt; &lt;pi&gt; &lt;+&gt; &lt;ln&gt; &lt;exp&gt;
-&lt;pi&gt; &lt;-&gt; &lt;ln&gt;.
-<P>
-or
-<P>
-10 &lt;enter&gt; 25 &lt;^&gt; &lt;atan&gt; &lt;tan&gt;
-<H2>Library Interface</h1>
-The calculator is implemented on top of a Java library that implements
-constructive real arithmetic.
-The library will live in com.sgi.math.
-It provides two interesting classes:
-<P>
-<A HREF="CR.java">CR</a> provides constructive reals as a subclass
-of <TT>Number</tt>. Its interface is described
-<A HREF="com/sgi/math/CR.html">here</a>.
-<P>
-<A HREF="UnaryCRFunction.java">UnaryCRFunction</a>
-provides some limited operations
-on unary functions over the constructive reals. It also provides a large
-number of constants for commonly used functions.
-Its interface is described
-<A HREF="com/sgi/math/UnaryCRFunction.html">here</a>.
-<P>
-Some general information on the implementation is <A HREF="impl.html">here</a>.
-<P>
-The entire calculator can be downloaded as a compressed tar file
-<A HREF="download/CRCalc.tar.gz">here</a>.
-<H2>Copyright</h2>
-The calculator and library code is copyrighted by Silicon Graphics, Inc.
-It may be used and redistributed subject to conditions specified
-<A HREF="COPYRIGHT.txt">here</a> and in the source files.
-<H2>Contact</h2>
-Please send comments or questions to
-<A HREF="mailto:Hans_Boehm@hp.com">Hans_Boehm@hp.com</a>.
-<A HREF="../index.html">Hans Boehm's home page</a>.
-</center>
-</body>
-</html>
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 7a3d824..0000000
--- a/Makefile
+++ /dev/null
@@ -1,55 +0,0 @@
-CALC_CLASSES=CRCalc.class calc_msg.class command_queue.class \
-command_queue_entry.class from_degrees_class.class time_slicer.class \
-to_degrees_class.class
-SOME_LIB_CLASSES=com/sgi/math/AbortedError.class com/sgi/math/CR.class \
-com/sgi/math/PrecisionOverflowError.class com/sgi/math/TestCR.class \
-com/sgi/math/UnaryCRFunction.class
-LIB_SOURCES=UnaryCRFunction.java CR.java PrecisionOverflowError.java AbortedError.java
-SOURCES=CRCalc.java TestCR.java rpn_calc.java $(LIB_SOURCES) \
-CRCalc.html CRCalc-force.html instrs.html Makefile COPYRIGHT.txt impl.html
-DOCFILES=com/sgi/math/UnaryCRFunction.html com/sgi/math/CR.html
-
-JAVA_PREFIX=/usr/java/bin
-JAVAC=$(JAVA_PREFIX)/javac
-JAVADOC=$(JAVA_PREFIX)/javadoc
-JAR=$(JAVA_PREFIX)/jar
-
-all: classes.jar download/CRCalc.tar.gz $(DOCFILES)
-
-classes.jar: $(CALC_CLASSES) $(SOME_LIB_CLASSES)
- $(JAR) cvf classes.jar $(CALC_CLASSES) com/sgi/math/*.class
-
-$(CALC_CLASSES): CRCalc.java $(SOME_LIB_CLASSES)
- $(JAVAC) CRCalc.java
-
-$(SOME_LIB_CLASSES): $(LIB_SOURCES) TestCR.java
- $(JAVAC) -d . $(LIB_SOURCES) TestCR.java
-
-download/CRCalc.tar.gz: $(SOURCES) download
- rm -f download/CRCalc.tar.gz
- tar cvf download/CRCalc.tar $(SOURCES)
- gzip download/CRCalc.tar
-
-download:
- mkdir download
-
-# gcj native compiled version of the command line calculator.
-# Requires installation of a recent gcj version.
-# Should build with or without threads.
-rpn_calc: rpn_calc.java $(LIB_SOURCES)
- gcj -O -o rpn_calc --main=rpn_calc rpn_calc.java $(LIB_SOURCES)
-
-TestCR: TestCR.java $(LIB_SOURCES)
- gcj -O -o TestCR --main=com.sgi.math.TestCR $(LIB_SOURCES)
-
-$(DOCFILES): CR.java UnaryCRFunction.java
- $(JAVADOC) -d . CR.java UnaryCRFunction.java
- rm -f tree.html
- rm -f packages.html
- rm -f AllNames.html
-
-clean:
- rm -f com/sgi/math/*.class
- rm -f classes.jar $(DOCFILES)
- rm -f *.class
- rm -f rpn_calc
diff --git a/instrs.html b/instrs.html
deleted file mode 100644
index 7ed0696..0000000
--- a/instrs.html
+++ /dev/null
@@ -1,285 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>Instructions for Constructive Reals Calculator</title>
-</head>
-<BODY BGCOLOR="#FFFFFF">
-<H1>
-<CENTER>CRCalc Instructions</center></h1>
-This is a calculator that operates on "exact" real numbers.
-More precisely, numbers are represented internally so that
-they can be evaluated to any needed precision. As a
-result, the displayed numbers are accurate to
-an error of strictly less than 1 digit in the last displayed
-digit, no matter how the number was computed. Subexpressions
-are evaluated to enough precision to ensure that cumulative
-rounding errors remain invisible.
-<P>
-The calculator uses "reverse polish notation". At any
-point the calculator contains a downward-growing stack of
-numbers. A number can be added to the bottom of the display
-by typing the digits and pressing the <enter> button.
-Most calculator operations operate on the bottom one or two
-numbers in the display, and replace them with the result
-of the operation. Thus 1 + 2 is entered as <B>1 enter 2 +</b>.
-<P>
-This entry method avoids the need for parentheses and makes
-better use of a two-dimensional display.
-<H2>Overview</h2>
-The calculator window is composed of several regions.
-From top to bottom they are.
-<DL>
-<DT>
-<B>The main display.</b>
-<DD>
-This displays numbers entered into the calculator and results.
-Newly entered or computed numbers appear toward the bottom of the
-display. If more numbers are entered than fit into the display,
-a scrollbar on the right can be used to move between them.
-<P>
-Calculator commands can be entered either by using the keypad
-(see below) or by typing with the display as the input focus.
-<DT>
-<B>Right-to-left scrolling control for the display.</b>
-<DD>
-Immediately below the display is a scrollbar and a small text
-window. Either can be used to control right-to-left scrolling
-of the display. At any point, the small text window displays the
-weight of the rightmost displayed digit. If the window reads -125,
-then the rightmost displayed digit is 125 digits to the right of
-the decimal point, and thus has weight 10<SUP>125</sup>.
-<P>
-This value can be adjusted either by editing the text window,
-or by using the slide control. Note that very large negative
-values are likely to require substantial time and memory to update
-the display. (Values below -1000 are likely to produce annoying
-pauses. Values below -10,000,000 are likely to result in error
-messages, possibly after a very long pause.)
-<P>
-Large positive values are likely to result in all significant
-digits moving to beyond the right side of the display. This
-is indicated by a display entry of <B>--></b>.
-<P>
-Note that the scrollbar has a comparatively limited range, and
-its resolution is far better near 0 than away from 0.
-<DT>
-<B>The keypad area.</b>
-<DD>
-This includes a control panel area on the left, and the main
-calculator keypad on the right. The control panel area includes
-several buttons whose labels change in response to the state
-of the calculator. These are often useful simply for determining
-calculator state.
-<DT>
-<B>The history window.</b>
-<DD>
-This includes recently entered commands, in the form
-in which they could have been typed on the computer keyboard.
-The text area is edit-able and, with the aid of the
-<B>replay</b> button, can be used to correct and replay
-previously entered commands. (On many platforms it also provides
-a somewhat clumsy mechanism for pasting in numbers from other sources
-which bypasses the restrictions on clipboard access from Java applets.)
-</dl>
-<H1>Keypad and keyboard commands</h1>
-Most commands can be entered either by clicking a keypad button on the
-screen, or by typing a single character on the computer keyboard.
-Here we list first the keypad label for the command, and then the
-equivalent keyboard characters for each command.
-They are listed approximately in the order in which they appear on the keypad.
-<DL>
-<DT>
-<B>1/x</b>, %
-<DD>
-Replace the last entry in the display by its reciprocal.
-The entry must be nonzero. A zero entry will cause the calculator
-to run until it is explicitly stopped, exhausts memory, or exceeds
-an internal limit on requested precision. (The calculator cannot
-determine whether an entry is exactly zero. You will be asked if
-you want to proceed if the entry appears to be zero. The recommended
-answer is "no" unless you believe the entry to be very small but nonzero.)
-<DT>
-<B>sqrt</b>, r, R
-<DD>
-Replace the last displayed entry by its square root. The entry
-must be nonnegative.
-<DT>
-<B>exp</b>, x, X
-<DD>
-Replace the last displayed entry <I>y</i> by <I>e<SUP>y</sup></i>.
-<DT>
-<B>ln</b>, l, L
-<DD>
-Replace the last displayed entry by its natural logarithm, i.e.
-logarithm base <I>e</i>. The entry must be positive. The
-base 10 logarithm can be computed by dividing by ln(10).
-<DT>
-<B>x^y</b>, ^
-<DD>
-If the second to the last entry is <I>x</i> and the last entry is
-<I>y</i>, replace them both by <I>x<SUP>y</sup></i>. Since this
-deals with arbitrary exponents, <I>x</i> is required to be positive.
-<DT>
-<B>C/CE</b>, #
-<DD>
-Clear either an incompletely entered number, or the bottom entry on
-the stack. The <backspace> key on the keyboard deletes just the
-last entered digit. If there is no incomplete entry, <backspace>
-behaves like #.
-<DT>
-<B>sin</b>, s
-<DD>
-Replace the last entry by its sine. By default, the argument is
-in radians. In degree mode, this and the next two functions
-interpret their argument as a number of degrees.
-<DT>
-<B>cos</b>, k
-<DD>
-Replace the last entry by its cosine.
-<DT>
-<B>tan</b>, t
-<DD>
-Replace the last entry by its tangent.
-<DT>
-<B>pi</b>, p
-<DD>
-Add the mathematical constant pi (the ratio of a circle's circumference
-to its diameter) to the end of the stack.
-<DT>
-<B>C All</b>, @
-<DD>
-Delete all numbers and any incomplete entries from the stack.
-<DT>
-<B>asin</b>, S
-<DD>
-Replace the last entry by its arcsine. The argument must be between
--1 and 1, inclusive. By default, the result is in radians and between -pi/2
-and pi/2. In degree mode, the answer is between -90 and 90.
-<DT>
-<B>acos</b>, K
-<DD>
-Replace the last entry by its arccosine. The argument must be between
--1 and 1, inclusive. The result is between 0 and pi (0 and 180).
-<DT>
-<B>atan</b>, T
-<DD>
-Replace the last entry by its arctangent. The result is between
--pi/2 and pi/2, exclusive, or between -90 and 90.
-<DT>
-<B>/</b>, /
-<DD>
-Divide the second to the last entry by the last one.
-Replace both by the result.
-The last one must be nonzero.
-<DT>
-<B>xchg</b>, i, I
-<DD>
-Exchange the last two entries on the stack.
-<DT>
-<B>*</b>, *
-<DD>
-Replace the last two stack entries by their product.
-<DT>
-<B>Store M</b>, =
-<DD>
-Copy the top of stack to a separate memory location.
-<DT>
-<B>-</b>, -
-<DD>
-Subtract the last stack entry from the previous one.
-Replace both by the result.
-<DT>
-<B>get M</b>, g
-<DD>
-Append the contents of the memory to the stack as the last entry.
-<DT>
-<B>+</b>, +
-<DD>
-Replace the last two entries on the stack by their sum.
-<DT>
-<B>copy</b>, q, Q
-<DD>
-Append a copy of the previously last stack entry as the last
-stack entry.
-<DT>
-<B>+/-</b>, ~
-<DD>
-Change the sign of the last stack entry, i.e. multiply it by -1.
-<DT>
-<B>enter</b>, $, &lt;blank&gt;, &lt;return&gt;
-<DD>
-Convert the previously entered digits (and possibly decimal point)
-into a real number and append it to the end of the stack.
-All other operations that affect or use the last stack entry do
-this implicitly before they perform their operation.
-Thus this is needed only if multiple numbers are appended
-to the stack without intervening arithmetic operations.
-<DT>
-<B>0</b>-<B>9</b>, 0-9
-<DD>
-Decimal digits used to enter numbers.
-<DT>
-<B>.</b>, .
-<DD>
-Decimal point for numeric entry.
-<DT>
-(no keypad equivalent), a-f
-<DD>
-Hexadecimal digits. Can be entered only from keyboard. Valid only
-in hexadecimal mode.
-</dl>
-<H2>Control Panel</h2>
-The control panel provides several additional keys and checkboxes which
-are used
-for purposes other than entering numbers or performing operation on
-the stack. Several of them also serve to indicate the
-calculator's state.
-state.
-<DL>
-<DT>
-<B>stop</b> or <B>STOP!</b>, (no keyboard equivalent)
-<DD>
-Aborts the operation of the calculator, <I>e.g.</i> after a nonterminating
-computation was inadvertently started. A label of "stop" indicates
-that the calculator is currently idle, and the button has no effect.
-If the button is labeled "STOP!", then a calculation is in progress.
-(Note that some Java implementations force a delayed response to this button.)
-<DT>
-<B>HELP!</b>, (no keyboard equivalent)
-<DD>
-Pop up a window with short instructions for the calculator.
-<DT>
-<B>replay</b>, (no keyboard equivalent)
-<DD>
-Interpret the selected text in the history window as command
-input to the calculator. This can be used to replay a previous
-computation with different inputs, or to add a number that was
-previously pasted into the history window to the calculator stack.
-Select the right commands in the history buffer before pushing
-this button.
-<DT>
-<B>write</b>, w, W
-<DD>
-Write the last entry on the stack to the Java console.
-The output includes all digits to the left of the rightmost one
-currently displayed, including those to the left of the display
-window. (Most browsers do not make the Java console visible by
-default, but provide an option to make it visible. Most also
-make it possible to copy text from the Java console to
-elsewhere on the desktop. It is generally not possible for
-Java Applets to write directly to the clipboard. Hence this
-option was chosen.)
-<DT>
-<B>base 16</b>, !
-<DD>
-A checkbox that allows selection of base 16 (hexadecimal) mode.
-This affects only number entry and display.
-To convert between bases, first enter the number and then switch bases.
-<DT>
-<B>degrees</b>, "
-<DD>
-A checkbox that allows selection of degree mode. Affects trignonometric
-and inverse trigonometric functions. Default is radian mode.
-</dl>
-</body>
-</html>
-
diff --git a/src/AbortedError.java b/src/AbortedError.java
index 4587b4f..f4fe8a3 100644
--- a/src/AbortedError.java
+++ b/src/AbortedError.java
@@ -1,9 +1,9 @@
-// Copyright (c) 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED
-//
+// Copyright (c) 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED
+//
// Permission is granted free of charge to copy, modify, use and distribute
// this software provided you include the entirety of this notice in all
// copies made.
-//
+//
// THIS SOFTWARE IS PROVIDED ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
// WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT
@@ -13,7 +13,7 @@
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES
// AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS
// AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
-//
+//
// UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING,
// WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY), CONTRACT, OR
// OTHERWISE, SHALL SGI BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL,
@@ -26,7 +26,7 @@
// LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
// EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT
// EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
-//
+//
// These license terms shall be governed by and construed in accordance with
// the laws of the United States and the State of California as applied to
// agreements entered into and to be performed entirely within California
@@ -34,7 +34,7 @@
// terms shall be subject to the exclusive jurisdiction of the Federal Courts
// of the Northern District of California (or, absent subject matter
// jurisdiction in such courts, the courts of the State of California), with
-// venue lying exclusively in Santa Clara County, California.
+// venue lying exclusively in Santa Clara County, California.
package com.sgi.math;
diff --git a/src/CR.java b/src/CR.java
index dcb5c2b..9a0c1d2 100644
--- a/src/CR.java
+++ b/src/CR.java
@@ -1,9 +1,9 @@
-// Copyright (c) 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED
-//
+// Copyright (c) 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED
+//
// Permission is granted free of charge to copy, modify, use and distribute
// this software provided you include the entirety of this notice in all
// copies made.
-//
+//
// THIS SOFTWARE IS PROVIDED ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
// WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT
@@ -13,7 +13,7 @@
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES
// AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS
// AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
-//
+//
// UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING,
// WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY), CONTRACT, OR
// OTHERWISE, SHALL SGI BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL,
@@ -26,7 +26,7 @@
// LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
// EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT
// EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
-//
+//
// These license terms shall be governed by and construed in accordance with
// the laws of the United States and the State of California as applied to
// agreements entered into and to be performed entirely within California
@@ -34,13 +34,13 @@
// terms shall be subject to the exclusive jurisdiction of the Federal Courts
// of the Northern District of California (or, absent subject matter
// jurisdiction in such courts, the courts of the State of California), with
-// venue lying exclusively in Santa Clara County, California.
+// venue lying exclusively in Santa Clara County, California.
// Added valueOf(string, radix), fixed some documentation comments.
-// Hans_Boehm@hp.com 1/12/2001
+// Hans_Boehm@hp.com 1/12/2001
// Fixed a serious typo in inv_CR(): For negative arguments it produced
-// the wrong sign. This affected the sign of divisions with
-// negative divisors. Hans_Boehm@hp.com 8/13/2001
+// the wrong sign. This affected the sign of divisions with
+// negative divisors. Hans_Boehm@hp.com 8/13/2001
package com.sgi.math;
@@ -98,7 +98,7 @@ import java.math.BigInteger;
* If the precision request generated during any subcalculation overflows
* a 28-bit integer. (This should be extremely unlikely, except as an
* outcome of a division by zero, or other erroneous computation.)
-*
+*
*/
public abstract class CR extends Number {
// CR is the basic representation of a number.
@@ -139,17 +139,17 @@ public volatile static boolean please_stop = false;
*/
protected abstract BigInteger approximate(int precision);
transient int min_prec;
- // The smallest precision value with which the above
- // has been called.
+ // The smallest precision value with which the above
+ // has been called.
transient BigInteger max_appr;
- // The scaled approximation corresponding to min_prec.
+ // The scaled approximation corresponding to min_prec.
transient boolean appr_valid = false;
- // min_prec and max_val are valid.
+ // min_prec and max_val are valid.
// Helper functions
static int bound_log2(int n) {
- int abs_n = Math.abs(n);
- return (int)Math.ceil(Math.log((double)(abs_n + 1))/Math.log(2.0));
+ int abs_n = Math.abs(n);
+ return (int)Math.ceil(Math.log((double)(abs_n + 1))/Math.log(2.0));
}
// Check that a precision is at least a factor of 8 away from
// overflowng the integer used to hold a precision spec.
@@ -157,15 +157,15 @@ public volatile static boolean please_stop = false;
// ourselves that none of the operations performed on precisions
// inside a function can generatean overflow.
static void check_prec(int n) {
- int high = n >> 28;
- // if n is not in danger of overflowing, then the 4 high order
- // bits should be identical. Thus high is either 0 or -1.
- // The rest of this is to test for either of those in a way
- // that should be as cheap as possible.
- int high_shifted = n >> 29;
- if (0 != (high ^ high_shifted)) {
- throw new PrecisionOverflowError();
- }
+ int high = n >> 28;
+ // if n is not in danger of overflowing, then the 4 high order
+ // bits should be identical. Thus high is either 0 or -1.
+ // The rest of this is to test for either of those in a way
+ // that should be as cheap as possible.
+ int high_shifted = n >> 29;
+ if (0 != (high ^ high_shifted)) {
+ throw new PrecisionOverflowError();
+ }
}
/**
@@ -173,74 +173,74 @@ public volatile static boolean please_stop = false;
* <TT>BigInteger</tt>.
*/
public static CR valueOf(BigInteger n) {
- return new int_CR(n);
+ return new int_CR(n);
}
/**
* The constructive real number corresponding to a
* Java <TT>int</tt>.
-*/
+*/
public static CR valueOf(int n) {
- return valueOf(BigInteger.valueOf(n));
+ return valueOf(BigInteger.valueOf(n));
}
/**
* The constructive real number corresponding to a
* Java <TT>long</tt>.
-*/
+*/
public static CR valueOf(long n) {
- return valueOf(BigInteger.valueOf(n));
+ return valueOf(BigInteger.valueOf(n));
}
/**
* The constructive real number corresponding to a
* Java <TT>double</tt>.
* The result is undefined if argument is infinite or NaN.
-*/
+*/
public static CR valueOf(double n) {
- if (Double.isNaN(n)) throw new ArithmeticException();
- if (Double.isInfinite(n)) throw new ArithmeticException();
- boolean negative = (n < 0.0);
- long bits = Double.doubleToLongBits(Math.abs(n));
- long mantissa = (bits & 0xfffffffffffffL);
- int biased_exp = (int)(bits >> 52);
- int exp = biased_exp - 1075;
- if (biased_exp != 0) {
- mantissa += (1L << 52);
- } else {
- mantissa <<= 1;
- }
- CR result = valueOf(mantissa).shiftLeft(exp);
- if (negative) result = result.negate();
- return result;
+ if (Double.isNaN(n)) throw new ArithmeticException();
+ if (Double.isInfinite(n)) throw new ArithmeticException();
+ boolean negative = (n < 0.0);
+ long bits = Double.doubleToLongBits(Math.abs(n));
+ long mantissa = (bits & 0xfffffffffffffL);
+ int biased_exp = (int)(bits >> 52);
+ int exp = biased_exp - 1075;
+ if (biased_exp != 0) {
+ mantissa += (1L << 52);
+ } else {
+ mantissa <<= 1;
+ }
+ CR result = valueOf(mantissa).shiftLeft(exp);
+ if (negative) result = result.negate();
+ return result;
}
/**
* The constructive real number corresponding to a
* Java <TT>float</tt>.
* The result is undefined if argument is infinite or NaN.
-*/
+*/
public static CR valueOf(float n) {
- return valueOf((double) n);
+ return valueOf((double) n);
}
static CR one = valueOf(1);
// Multiply k by 2**n.
static BigInteger shift(BigInteger k, int n) {
- if (n == 0) return k;
- if (n < 0) return k.shiftRight(-n);
- return k.shiftLeft(n);
+ if (n == 0) return k;
+ if (n < 0) return k.shiftRight(-n);
+ return k.shiftLeft(n);
}
// Multiply by 2**n, rounding result
static BigInteger scale(BigInteger k, int n) {
- if (n >= 0) {
- return k.shiftLeft(n);
- } else {
- BigInteger adj_k = shift(k, n+1).add(big1);
+ if (n >= 0) {
+ return k.shiftLeft(n);
+ } else {
+ BigInteger adj_k = shift(k, n+1).add(big1);
return adj_k.shiftRight(1);
- }
+ }
}
// Identical to approximate(), but maintain and update cache.
@@ -252,28 +252,28 @@ public volatile static boolean please_stop = false;
* Normally not overridden, and called only from <TT>approximate</tt>
* methods in subclasses. Not needed if the provided operations
* on constructive reals suffice.
-*/
+*/
public BigInteger get_appr(int precision) {
- check_prec(precision);
- if (appr_valid && precision >= min_prec) {
- return scale(max_appr, min_prec - precision);
- } else {
- BigInteger result = approximate(precision);
- min_prec = precision;
- max_appr = result;
- appr_valid = true;
- return result;
- }
+ check_prec(precision);
+ if (appr_valid && precision >= min_prec) {
+ return scale(max_appr, min_prec - precision);
+ } else {
+ BigInteger result = approximate(precision);
+ min_prec = precision;
+ max_appr = result;
+ appr_valid = true;
+ return result;
+ }
}
// Return the position of the msd.
// If x.msd() == n then
- // 2**(n-1) < abs(x) < 2**(n+1)
+ // 2**(n-1) < abs(x) < 2**(n+1)
// This initial version assumes that max_appr is valid
// and sufficiently removed from zero
// that the msd is determined.
int known_msd() {
- int first_digit;
+ int first_digit;
int length;
if (max_appr.signum() >= 0) {
length = max_appr.bitLength();
@@ -283,20 +283,20 @@ public volatile static boolean please_stop = false;
first_digit = min_prec + length - 1;
return first_digit;
}
-
+
// This version may return Integer.MIN_VALUE if the correct
// answer is < n.
int msd(int n) {
- if (!appr_valid ||
- max_appr.compareTo(big1) <= 0
- && max_appr.compareTo(bigm1) >= 0) {
- get_appr(n - 1);
- if (max_appr.abs().compareTo(big1) <= 0) {
- // msd could still be arbitrarily far to the right.
- return Integer.MIN_VALUE;
- }
- }
- return known_msd();
+ if (!appr_valid ||
+ max_appr.compareTo(big1) <= 0
+ && max_appr.compareTo(bigm1) >= 0) {
+ get_appr(n - 1);
+ if (max_appr.abs().compareTo(big1) <= 0) {
+ // msd could still be arbitrarily far to the right.
+ return Integer.MIN_VALUE;
+ }
+ }
+ return known_msd();
}
@@ -304,14 +304,14 @@ public volatile static boolean please_stop = false;
// precision.
int iter_msd(int n)
{
- int prec = 0;
-
- for (;prec > n + 30; prec = (prec * 3)/2 - 16) {
- int msd = msd(prec);
- if (msd != Integer.MIN_VALUE) return msd;
- check_prec(prec);
- if (Thread.interrupted() || please_stop) throw new AbortedError();
- }
+ int prec = 0;
+
+ for (;prec > n + 30; prec = (prec * 3)/2 - 16) {
+ int msd = msd(prec);
+ if (msd != Integer.MIN_VALUE) return msd;
+ check_prec(prec);
+ if (Thread.interrupted() || please_stop) throw new AbortedError();
+ }
return msd(n);
}
@@ -319,40 +319,40 @@ public volatile static boolean please_stop = false;
// that it loops forever (or throws an exception when the
// requested precision overflows) if this constructive real is zero.
int msd() {
- return iter_msd(Integer.MIN_VALUE);
+ return iter_msd(Integer.MIN_VALUE);
}
// A helper function for toString.
// Generate a String containing n zeroes.
private static String zeroes(int n) {
- char[] a = new char[n];
- for (int i = 0; i < n; ++i) {
- a[i] = '0';
- }
+ char[] a = new char[n];
+ for (int i = 0; i < n; ++i) {
+ a[i] = '0';
+ }
return new String(a);
- }
+ }
// Natural log of 2. Needed for some prescaling below.
// ln(2) = 7ln(10/9) - 2ln(25/24) + 3ln(81/80)
- CR simple_ln() {
- return new prescaled_ln_CR(this.subtract(one));
- }
- static CR ten_ninths = valueOf(10).divide(valueOf(9));
- static CR twentyfive_twentyfourths = valueOf(25).divide(valueOf(24));
- static CR eightyone_eightyeths = valueOf(81).divide(valueOf(80));
- static CR ln2_1 = valueOf(7).multiply(ten_ninths.simple_ln());
- static CR ln2_2 =
- valueOf(2).multiply(twentyfive_twentyfourths.simple_ln());
- static CR ln2_3 = valueOf(3).multiply(eightyone_eightyeths.simple_ln());
- static CR ln2 = ln2_1.subtract(ln2_2).add(ln2_3);
+ CR simple_ln() {
+ return new prescaled_ln_CR(this.subtract(one));
+ }
+ static CR ten_ninths = valueOf(10).divide(valueOf(9));
+ static CR twentyfive_twentyfourths = valueOf(25).divide(valueOf(24));
+ static CR eightyone_eightyeths = valueOf(81).divide(valueOf(80));
+ static CR ln2_1 = valueOf(7).multiply(ten_ninths.simple_ln());
+ static CR ln2_2 =
+ valueOf(2).multiply(twentyfive_twentyfourths.simple_ln());
+ static CR ln2_3 = valueOf(3).multiply(eightyone_eightyeths.simple_ln());
+ static CR ln2 = ln2_1.subtract(ln2_2).add(ln2_3);
// Atan of integer reciprocal. Used for PI. Could perhaps
// be made public.
- static CR atan_reciprocal(int n) {
- return new integral_atan_CR(n);
- }
+ static CR atan_reciprocal(int n) {
+ return new integral_atan_CR(n);
+ }
// Other constants used for PI computation.
- static CR four = valueOf(4);
+ static CR four = valueOf(4);
// Public operations.
/**
@@ -362,19 +362,19 @@ public volatile static boolean please_stop = false;
* they differ by less than the tolerance, anything
* may happen. The tolerance allowed is
* the maximum of (abs(this)+abs(x))*(2**r) and 2**a
-* @param x The other constructive real
-* @param r Relative tolerance in bits
-* @param a Absolute tolerance in bits
+* @param x The other constructive real
+* @param r Relative tolerance in bits
+* @param a Absolute tolerance in bits
*/
public int compareTo(CR x, int r, int a) {
- int this_msd = iter_msd(a);
- int x_msd = x.iter_msd(this_msd > a? this_msd : a);
- int max_msd = (x_msd > this_msd? x_msd : this_msd);
- int rel = max_msd + r;
- // This can't approach overflow, since r and a are
- // effectively divided by 2, and msds are checked.
- int abs_prec = (rel > a? rel : a);
- return compareTo(x, abs_prec);
+ int this_msd = iter_msd(a);
+ int x_msd = x.iter_msd(this_msd > a? this_msd : a);
+ int max_msd = (x_msd > this_msd? x_msd : this_msd);
+ int rel = max_msd + r;
+ // This can't approach overflow, since r and a are
+ // effectively divided by 2, and msds are checked.
+ int abs_prec = (rel > a? rel : a);
+ return compareTo(x, abs_prec);
}
/**
@@ -384,18 +384,18 @@ public volatile static boolean please_stop = false;
* Result is 0 if both constructive reals are equal, indeterminate
* if they differ by less than 2**a.
*
-* @param x The other constructive real
-* @param a Absolute tolerance in bits
+* @param x The other constructive real
+* @param a Absolute tolerance in bits
*/
public int compareTo(CR x, int a) {
- int needed_prec = a - 1;
- BigInteger this_appr = get_appr(needed_prec);
- BigInteger x_appr = x.get_appr(needed_prec);
- int comp1 = this_appr.compareTo(x_appr.add(big1));
- if (comp1 > 0) return 1;
- int comp2 = this_appr.compareTo(x_appr.subtract(big1));
- if (comp2 < 0) return -1;
- return 0;
+ int needed_prec = a - 1;
+ BigInteger this_appr = get_appr(needed_prec);
+ BigInteger x_appr = x.get_appr(needed_prec);
+ int comp1 = this_appr.compareTo(x_appr.add(big1));
+ if (comp1 > 0) return 1;
+ int comp2 = this_appr.compareTo(x_appr.subtract(big1));
+ if (comp2 < 0) return -1;
+ return 0;
}
/**
@@ -407,24 +407,24 @@ public volatile static boolean please_stop = false;
* version of compareTo should be used.
*/
public int compareTo(CR x) {
- for (int a = -20; ; a *= 2) {
- check_prec(a);
- int result = compareTo(x, a);
- if (0 != result) return result;
- }
+ for (int a = -20; ; a *= 2) {
+ check_prec(a);
+ int result = compareTo(x, a);
+ if (0 != result) return result;
+ }
}
/**
* Equivalent to <TT>compareTo(CR.valueOf(0), a)</tt>
*/
public int signum(int a) {
- if (appr_valid) {
- int quick_try = max_appr.signum();
- if (0 != quick_try) return quick_try;
- }
- int needed_prec = a - 1;
+ if (appr_valid) {
+ int quick_try = max_appr.signum();
+ if (0 != quick_try) return quick_try;
+ }
+ int needed_prec = a - 1;
BigInteger this_appr = get_appr(needed_prec);
- return this_appr.signum();
+ return this_appr.signum();
}
/**
@@ -436,94 +436,94 @@ public volatile static boolean please_stop = false;
* version of signum should be used.
*/
public int signum() {
- for (int a = -20; ; a *= 2) {
- check_prec(a);
- int result = signum(a);
- if (0 != result) return result;
- }
+ for (int a = -20; ; a *= 2) {
+ check_prec(a);
+ int result = signum(a);
+ if (0 != result) return result;
+ }
}
/**
* Return the constructive real number corresponding to the given
* textual representation and radix.
*
-* @param s [-] digit* [. digit*]
-* @param radix
+* @param s [-] digit* [. digit*]
+* @param radix
*/
public static CR valueOf(String s, int radix)
- throws NumberFormatException {
- int len = s.length();
- int start_pos = 0, point_pos;
- String fraction;
- while (s.charAt(start_pos) == ' ') ++start_pos;
- while (s.charAt(len - 1) == ' ') --len;
- point_pos = s.indexOf('.', start_pos);
- if (point_pos == -1) {
- point_pos = len;
- fraction = "0";
- } else {
- fraction = s.substring(point_pos + 1, len);
- }
- String whole = s.substring(start_pos, point_pos);
- BigInteger scaled_result = new BigInteger(whole + fraction, radix);
- BigInteger divisor = BigInteger.valueOf(radix).pow(fraction.length());
- return CR.valueOf(scaled_result).divide(CR.valueOf(divisor));
+ throws NumberFormatException {
+ int len = s.length();
+ int start_pos = 0, point_pos;
+ String fraction;
+ while (s.charAt(start_pos) == ' ') ++start_pos;
+ while (s.charAt(len - 1) == ' ') --len;
+ point_pos = s.indexOf('.', start_pos);
+ if (point_pos == -1) {
+ point_pos = len;
+ fraction = "0";
+ } else {
+ fraction = s.substring(point_pos + 1, len);
+ }
+ String whole = s.substring(start_pos, point_pos);
+ BigInteger scaled_result = new BigInteger(whole + fraction, radix);
+ BigInteger divisor = BigInteger.valueOf(radix).pow(fraction.length());
+ return CR.valueOf(scaled_result).divide(CR.valueOf(divisor));
}
-
+
/**
* Return a textual representation accurate to <TT>n</tt> places
* to the right of the decimal point. <TT>n</tt> must be nonnegative.
*
-* @param n Number of digits included to the right of decimal point
-* @param radix Base ( >= 2, <= 16) for the resulting representation.
+* @param n Number of digits included to the right of decimal point
+* @param radix Base ( >= 2, <= 16) for the resulting representation.
*/
public String toString(int n, int radix) {
- CR scaled_CR;
- if (16 == radix) {
- scaled_CR = shiftLeft(4*n);
- } else {
- BigInteger scale_factor = BigInteger.valueOf(radix).pow(n);
- scaled_CR = multiply(new int_CR(scale_factor));
- }
- BigInteger scaled_int = scaled_CR.get_appr(0);
- String scaled_string = scaled_int.abs().toString(radix);
- String result;
- if (0 == n) {
- result = scaled_string;
- } else {
- int len = scaled_string.length();
- if (len <= n) {
- // Add sufficient leading zeroes
- String z = zeroes(n + 1 - len);
- scaled_string = z + scaled_string;
- len = n + 1;
- }
- String whole = scaled_string.substring(0, len - n);
- String fraction = scaled_string.substring(len - n);
- result = whole + "." + fraction;
- }
- if (scaled_int.signum() < 0) {
- result = "-" + result;
- }
- return result;
+ CR scaled_CR;
+ if (16 == radix) {
+ scaled_CR = shiftLeft(4*n);
+ } else {
+ BigInteger scale_factor = BigInteger.valueOf(radix).pow(n);
+ scaled_CR = multiply(new int_CR(scale_factor));
+ }
+ BigInteger scaled_int = scaled_CR.get_appr(0);
+ String scaled_string = scaled_int.abs().toString(radix);
+ String result;
+ if (0 == n) {
+ result = scaled_string;
+ } else {
+ int len = scaled_string.length();
+ if (len <= n) {
+ // Add sufficient leading zeroes
+ String z = zeroes(n + 1 - len);
+ scaled_string = z + scaled_string;
+ len = n + 1;
+ }
+ String whole = scaled_string.substring(0, len - n);
+ String fraction = scaled_string.substring(len - n);
+ result = whole + "." + fraction;
+ }
+ if (scaled_int.signum() < 0) {
+ result = "-" + result;
+ }
+ return result;
}
/**
* Equivalent to <TT>toString(n,10)</tt>
*
-* @param n Number of digits included to the right of decimal point
+* @param n Number of digits included to the right of decimal point
*/
public String toString(int n) {
- return toString(n, 10);
+ return toString(n, 10);
}
/**
* Equivalent to <TT>toString(10, 10)</tt>
*/
public String toString() {
- return toString(10);
+ return toString(10);
}
/**
@@ -531,7 +531,7 @@ public volatile static boolean please_stop = false;
* constructive real.
*/
public BigInteger BigIntegerValue() {
- return get_appr(0);
+ return get_appr(0);
}
/**
@@ -539,7 +539,7 @@ public volatile static boolean please_stop = false;
* constructive real. Behavior on overflow is undefined.
*/
public int intValue() {
- return BigIntegerValue().intValue();
+ return BigIntegerValue().intValue();
}
/**
@@ -547,7 +547,7 @@ public volatile static boolean please_stop = false;
* constructive real. Behavior on overflow is undefined.
*/
public long longValue() {
- return BigIntegerValue().longValue();
+ return BigIntegerValue().longValue();
}
/**
@@ -555,30 +555,30 @@ public volatile static boolean please_stop = false;
* represented bit from the constructive real.
*/
public double doubleValue() {
- int my_msd = iter_msd(-1080 /* slightly > exp. range */);
- if (Integer.MIN_VALUE == my_msd) return 0.0;
- int needed_prec = my_msd - 60;
- double scaled_int = get_appr(needed_prec).doubleValue();
- boolean may_underflow = (needed_prec < -1000);
- long scaled_int_rep = Double.doubleToLongBits(scaled_int);
- long exp_adj = may_underflow? needed_prec + 96 : needed_prec;
- long orig_exp = (scaled_int_rep >> 52) & 0x7ff;
+ int my_msd = iter_msd(-1080 /* slightly > exp. range */);
+ if (Integer.MIN_VALUE == my_msd) return 0.0;
+ int needed_prec = my_msd - 60;
+ double scaled_int = get_appr(needed_prec).doubleValue();
+ boolean may_underflow = (needed_prec < -1000);
+ long scaled_int_rep = Double.doubleToLongBits(scaled_int);
+ long exp_adj = may_underflow? needed_prec + 96 : needed_prec;
+ long orig_exp = (scaled_int_rep >> 52) & 0x7ff;
if (((orig_exp + exp_adj) & ~0x7ff) != 0) {
- // overflow
- if (scaled_int < 0.0) {
- return Double.NEGATIVE_INFINITY;
- } else {
- return Double.POSITIVE_INFINITY;
- }
- }
- scaled_int_rep += exp_adj << 52;
- double result = Double.longBitsToDouble(scaled_int_rep);
- if (may_underflow) {
- double two48 = (double)(1 << 48);
- return result/two48/two48;
- } else {
- return result;
- }
+ // overflow
+ if (scaled_int < 0.0) {
+ return Double.NEGATIVE_INFINITY;
+ } else {
+ return Double.POSITIVE_INFINITY;
+ }
+ }
+ scaled_int_rep += exp_adj << 52;
+ double result = Double.longBitsToDouble(scaled_int_rep);
+ if (may_underflow) {
+ double two48 = (double)(1 << 48);
+ return result/two48/two48;
+ } else {
+ return result;
+ }
}
/**
@@ -586,7 +586,7 @@ public volatile static boolean please_stop = false;
* represented bit from the constructive real.
*/
public float floatValue() {
- return (float)doubleValue();
+ return (float)doubleValue();
}
/**
@@ -598,20 +598,20 @@ public volatile static boolean please_stop = false;
/**
* Multiply a constructive real by 2**n.
-* @param n shift count, may be negative
+* @param n shift count, may be negative
*/
public CR shiftLeft(int n) {
- check_prec(n);
- return new shifted_CR(this, n);
+ check_prec(n);
+ return new shifted_CR(this, n);
}
/**
* Multiply a constructive real by 2**(-n).
-* @param n shift count, may be negative
+* @param n shift count, may be negative
*/
public CR shiftRight(int n) {
- check_prec(n);
- return new shifted_CR(this, -n);
+ check_prec(n);
+ return new shifted_CR(this, -n);
}
/**
@@ -657,21 +657,21 @@ public volatile static boolean please_stop = false;
* a useful alternative to conditionals.
*/
public CR select(CR x, CR y) {
- return new select_CR(this, x, y);
+ return new select_CR(this, x, y);
}
/**
* The maximum of two constructive reals.
*/
public CR max(CR x) {
- return subtract(x).select(x, this);
+ return subtract(x).select(x, this);
}
/**
* The minimum of two constructive reals.
*/
public CR min(CR x) {
- return subtract(x).select(this, x);
+ return subtract(x).select(this, x);
}
/**
@@ -679,21 +679,21 @@ public volatile static boolean please_stop = false;
* Note that this cannot be written as a conditional.
*/
public CR abs() {
- return select(negate(), this);
+ return select(negate(), this);
}
/**
* The exponential function, i.e. e**<TT>this</tt>.
*/
public CR exp() {
- final int low_prec = -10;
- BigInteger rough_appr = get_appr(low_prec);
- if (rough_appr.signum() < 0) return negate().exp().inverse();
- if (rough_appr.compareTo(big2) > 0) {
- CR square_root = shiftRight(1).exp();
- return square_root.multiply(square_root);
- } else {
- return new prescaled_exp_CR(this);
+ final int low_prec = -10;
+ BigInteger rough_appr = get_appr(low_prec);
+ if (rough_appr.signum() < 0) return negate().exp().inverse();
+ if (rough_appr.compareTo(big2) > 0) {
+ CR square_root = shiftRight(1).exp();
+ return square_root.multiply(square_root);
+ } else {
+ return new prescaled_exp_CR(this);
}
}
@@ -703,77 +703,77 @@ public volatile static boolean please_stop = false;
* The ratio of a circle's circumference to its diameter.
*/
public static CR PI = four.multiply(four.multiply(atan_reciprocal(5))
- .subtract(atan_reciprocal(239)));
- // pi/4 = 4*atan(1/5) - atan(1/239)
+ .subtract(atan_reciprocal(239)));
+ // pi/4 = 4*atan(1/5) - atan(1/239)
static CR half_pi = PI.shiftRight(1);
/**
* The trigonometric cosine function.
*/
public CR cos() {
- BigInteger rough_appr = get_appr(-1);
- BigInteger abs_rough_appr = rough_appr.abs();
- if (abs_rough_appr.compareTo(big6) >= 0) {
- // Subtract multiples of PI
- BigInteger multiplier = rough_appr.divide(big6);
- CR adjustment = PI.multiply(CR.valueOf(multiplier));
- if (multiplier.and(big1).signum() != 0) {
- return subtract(adjustment).cos().negate();
- } else {
- return subtract(adjustment).cos();
- }
- } else if (abs_rough_appr.compareTo(big2) >= 0) {
- // Scale further with double angle formula
- CR cos_half = shiftRight(1).cos();
- return cos_half.multiply(cos_half).shiftLeft(1).subtract(one);
- } else {
- return new prescaled_cos_CR(this);
- }
+ BigInteger rough_appr = get_appr(-1);
+ BigInteger abs_rough_appr = rough_appr.abs();
+ if (abs_rough_appr.compareTo(big6) >= 0) {
+ // Subtract multiples of PI
+ BigInteger multiplier = rough_appr.divide(big6);
+ CR adjustment = PI.multiply(CR.valueOf(multiplier));
+ if (multiplier.and(big1).signum() != 0) {
+ return subtract(adjustment).cos().negate();
+ } else {
+ return subtract(adjustment).cos();
+ }
+ } else if (abs_rough_appr.compareTo(big2) >= 0) {
+ // Scale further with double angle formula
+ CR cos_half = shiftRight(1).cos();
+ return cos_half.multiply(cos_half).shiftLeft(1).subtract(one);
+ } else {
+ return new prescaled_cos_CR(this);
+ }
}
/**
* The trigonometric sine function.
*/
public CR sin() {
- return half_pi.subtract(this).cos();
+ return half_pi.subtract(this).cos();
}
static final BigInteger low_ln_limit = big8; /* sixteenths, i.e. 1/2 */
static final BigInteger high_ln_limit =
- BigInteger.valueOf(16 + 8 /* 1.5 */);
- static final BigInteger scaled_4 =
- BigInteger.valueOf(4*16);
+ BigInteger.valueOf(16 + 8 /* 1.5 */);
+ static final BigInteger scaled_4 =
+ BigInteger.valueOf(4*16);
/**
* The natural (base e) logarithm.
*/
public CR ln() {
- final int low_prec = -4;
- BigInteger rough_appr = get_appr(low_prec); /* In sixteenths */
- if (rough_appr.compareTo(big0) < 0) {
- throw new ArithmeticException();
- }
- if (rough_appr.compareTo(low_ln_limit) <= 0) {
- return inverse().ln().negate();
- }
- if (rough_appr.compareTo(high_ln_limit) >= 0) {
- if (rough_appr.compareTo(scaled_4) <= 0) {
- CR quarter = sqrt().sqrt().ln();
- return quarter.shiftLeft(2);
- } else {
- int extra_bits = rough_appr.bitLength() - 3;
- CR scaled_result = shiftRight(extra_bits).ln();
- return scaled_result.add(CR.valueOf(extra_bits).multiply(ln2));
- }
- }
- return simple_ln();
+ final int low_prec = -4;
+ BigInteger rough_appr = get_appr(low_prec); /* In sixteenths */
+ if (rough_appr.compareTo(big0) < 0) {
+ throw new ArithmeticException();
+ }
+ if (rough_appr.compareTo(low_ln_limit) <= 0) {
+ return inverse().ln().negate();
+ }
+ if (rough_appr.compareTo(high_ln_limit) >= 0) {
+ if (rough_appr.compareTo(scaled_4) <= 0) {
+ CR quarter = sqrt().sqrt().ln();
+ return quarter.shiftLeft(2);
+ } else {
+ int extra_bits = rough_appr.bitLength() - 3;
+ CR scaled_result = shiftRight(extra_bits).ln();
+ return scaled_result.add(CR.valueOf(extra_bits).multiply(ln2));
+ }
+ }
+ return simple_ln();
}
/**
* The square root of a constructive real.
*/
public CR sqrt() {
- return new sqrt_CR(this);
+ return new sqrt_CR(this);
}
} // end of CR
@@ -793,18 +793,18 @@ abstract class slow_CR extends CR {
static int max_prec = -64;
static int prec_incr = 32;
public BigInteger get_appr(int precision) {
- check_prec(precision);
- if (appr_valid && precision >= min_prec) {
- return scale(max_appr, min_prec - precision);
- } else {
- int eval_prec = (precision >= max_prec? max_prec :
- (precision - prec_incr + 1) & ~(prec_incr - 1));
- BigInteger result = approximate(eval_prec);
- min_prec = eval_prec;
- max_appr = result;
- appr_valid = true;
- return scale(result, eval_prec - precision);
- }
+ check_prec(precision);
+ if (appr_valid && precision >= min_prec) {
+ return scale(max_appr, min_prec - precision);
+ } else {
+ int eval_prec = (precision >= max_prec? max_prec :
+ (precision - prec_incr + 1) & ~(prec_incr - 1));
+ BigInteger result = approximate(eval_prec);
+ min_prec = eval_prec;
+ max_appr = result;
+ appr_valid = true;
+ return scale(result, eval_prec - precision);
+ }
}
}
@@ -813,10 +813,10 @@ abstract class slow_CR extends CR {
class int_CR extends CR {
BigInteger value;
int_CR(BigInteger n) {
- value = n;
+ value = n;
}
protected BigInteger approximate(int p) {
- return scale(value, -p) ;
+ return scale(value, -p) ;
}
}
@@ -825,14 +825,14 @@ class add_CR extends CR {
CR op1;
CR op2;
add_CR(CR x, CR y) {
- op1 = x;
- op2 = y;
+ op1 = x;
+ op2 = y;
}
protected BigInteger approximate(int p) {
- // Args need to be evaluated so that each error is < 1/4 ulp.
- // Rounding error from the cale call is <= 1/2 ulp, so that
- // final error is < 1 ulp.
- return scale(op1.get_appr(p-2).add(op2.get_appr(p-2)), -2);
+ // Args need to be evaluated so that each error is < 1/4 ulp.
+ // Rounding error from the cale call is <= 1/2 ulp, so that
+ // final error is < 1 ulp.
+ return scale(op1.get_appr(p-2).add(op2.get_appr(p-2)), -2);
}
}
@@ -841,11 +841,11 @@ class shifted_CR extends CR {
CR op;
int count;
shifted_CR(CR x, int n) {
- op = x;
- count = n;
+ op = x;
+ count = n;
}
protected BigInteger approximate(int p) {
- return op.get_appr(p - count);
+ return op.get_appr(p - count);
}
}
@@ -853,47 +853,47 @@ class shifted_CR extends CR {
class neg_CR extends CR {
CR op;
neg_CR(CR x) {
- op = x;
+ op = x;
}
protected BigInteger approximate(int p) {
- return op.get_appr(p).negate();
+ return op.get_appr(p).negate();
}
}
// Representation of:
-// op1 if selector < 0
-// op2 if selector >= 0
-// Assumes x = y if s = 0
+// op1 if selector < 0
+// op2 if selector >= 0
+// Assumes x = y if s = 0
class select_CR extends CR {
CR selector;
int selector_sign;
CR op1;
CR op2;
select_CR(CR s, CR x, CR y) {
- selector = s;
- int selector_sign = selector.get_appr(-20).signum();
- op1 = x;
- op2 = y;
+ selector = s;
+ int selector_sign = selector.get_appr(-20).signum();
+ op1 = x;
+ op2 = y;
}
protected BigInteger approximate(int p) {
- if (selector_sign < 0) return op1.get_appr(p);
- if (selector_sign > 0) return op2.get_appr(p);
- BigInteger op1_appr = op1.get_appr(p-1);
- BigInteger op2_appr = op2.get_appr(p-1);
- BigInteger diff = op1_appr.subtract(op2_appr).abs();
- if (diff.compareTo(big1) <= 0) {
- // close enough; use either
- return scale(op1_appr, -1);
- }
- // op1 and op2 are different; selector != 0;
- // safe to get sign of selector.
- if (selector.signum() < 0) {
- selector_sign = -1;
- return scale(op1_appr, -1);
- } else {
- selector_sign = 1;
- return scale(op2_appr, -1);
- }
+ if (selector_sign < 0) return op1.get_appr(p);
+ if (selector_sign > 0) return op2.get_appr(p);
+ BigInteger op1_appr = op1.get_appr(p-1);
+ BigInteger op2_appr = op2.get_appr(p-1);
+ BigInteger diff = op1_appr.subtract(op2_appr).abs();
+ if (diff.compareTo(big1) <= 0) {
+ // close enough; use either
+ return scale(op1_appr, -1);
+ }
+ // op1 and op2 are different; selector != 0;
+ // safe to get sign of selector.
+ if (selector.signum() < 0) {
+ selector_sign = -1;
+ return scale(op1_appr, -1);
+ } else {
+ selector_sign = 1;
+ return scale(op2_appr, -1);
+ }
}
}
@@ -902,44 +902,44 @@ class mult_CR extends CR {
CR op1;
CR op2;
mult_CR(CR x, CR y) {
- op1 = x;
- op2 = y;
+ op1 = x;
+ op2 = y;
}
protected BigInteger approximate(int p) {
- int half_prec = (p >> 1) - 1;
- int msd_op1 = op1.msd(half_prec);
- int msd_op2;
-
- if (msd_op1 == Integer.MIN_VALUE) {
- msd_op2 = op2.msd(half_prec);
- if (msd_op2 == Integer.MIN_VALUE) {
- // Product is small enough that zero will do as an
- // approximation.
- return big0;
- } else {
- // Swap them, so the larger operand (in absolute value)
- // is first.
- CR tmp;
- tmp = op1;
- op1 = op2;
- op2 = tmp;
- msd_op1 = msd_op2;
- }
- }
- // msd_op1 is valid at this point.
- int prec2 = p - msd_op1 - 3; // Precision needed for op2.
- // The appr. error is multiplied by at most
- // 2 ** (msd_op1 + 1)
- // Thus each approximation contributes 1/4 ulp
- // to the rounding error, and the final rounding adds
- // another 1/2 ulp.
- BigInteger appr2 = op2.get_appr(prec2);
+ int half_prec = (p >> 1) - 1;
+ int msd_op1 = op1.msd(half_prec);
+ int msd_op2;
+
+ if (msd_op1 == Integer.MIN_VALUE) {
+ msd_op2 = op2.msd(half_prec);
+ if (msd_op2 == Integer.MIN_VALUE) {
+ // Product is small enough that zero will do as an
+ // approximation.
+ return big0;
+ } else {
+ // Swap them, so the larger operand (in absolute value)
+ // is first.
+ CR tmp;
+ tmp = op1;
+ op1 = op2;
+ op2 = tmp;
+ msd_op1 = msd_op2;
+ }
+ }
+ // msd_op1 is valid at this point.
+ int prec2 = p - msd_op1 - 3; // Precision needed for op2.
+ // The appr. error is multiplied by at most
+ // 2 ** (msd_op1 + 1)
+ // Thus each approximation contributes 1/4 ulp
+ // to the rounding error, and the final rounding adds
+ // another 1/2 ulp.
+ BigInteger appr2 = op2.get_appr(prec2);
if (appr2.signum() == 0) return big0;
- msd_op2 = op2.known_msd();
- int prec1 = p - msd_op2 - 3; // Precision needed for op1.
- BigInteger appr1 = op1.get_appr(prec1);
- int scale_digits = prec1 + prec2 - p;
- return scale(appr1.multiply(appr2), scale_digits);
+ msd_op2 = op2.known_msd();
+ int prec1 = p - msd_op2 - 3; // Precision needed for op1.
+ BigInteger appr1 = op1.get_appr(prec1);
+ int scale_digits = prec1 + prec2 - p;
+ return scale(appr1.multiply(appr2), scale_digits);
}
}
@@ -949,37 +949,37 @@ class inv_CR extends CR {
CR op;
inv_CR(CR x) { op = x; }
protected BigInteger approximate(int p) {
- int msd = op.msd();
- int inv_msd = 1 - msd;
- int digits_needed = inv_msd - p + 3;
- // Number of SIGNIFICANT digits needed for
- // argument, excl. msd position, which may
- // be fictitious, since msd routine can be
- // off by 1. Roughly 1 extra digit is
- // needed since the relative error is the
- // same in the argument and result, but
- // this isn't quite the same as the number
- // of significant digits. Another digit
- // is needed to compensate for slop in the
+ int msd = op.msd();
+ int inv_msd = 1 - msd;
+ int digits_needed = inv_msd - p + 3;
+ // Number of SIGNIFICANT digits needed for
+ // argument, excl. msd position, which may
+ // be fictitious, since msd routine can be
+ // off by 1. Roughly 1 extra digit is
+ // needed since the relative error is the
+ // same in the argument and result, but
+ // this isn't quite the same as the number
+ // of significant digits. Another digit
+ // is needed to compensate for slop in the
// calculation.
- // One further bit is required, since the
- // final rounding introduces a 0.5 ulp
- // error.
- int prec_needed = msd - digits_needed;
- int log_scale_factor = -p - prec_needed;
- if (log_scale_factor < 0) return big0;
- BigInteger dividend = big1.shiftLeft(log_scale_factor);
- BigInteger scaled_divisor = op.get_appr(prec_needed);
- BigInteger abs_scaled_divisor = scaled_divisor.abs();
- BigInteger adj_dividend = dividend.add(
- abs_scaled_divisor.shiftRight(1));
- // Adjustment so that final result is rounded.
- BigInteger result = adj_dividend.divide(abs_scaled_divisor);
- if (scaled_divisor.signum() < 0) {
- return result.negate();
- } else {
- return result;
- }
+ // One further bit is required, since the
+ // final rounding introduces a 0.5 ulp
+ // error.
+ int prec_needed = msd - digits_needed;
+ int log_scale_factor = -p - prec_needed;
+ if (log_scale_factor < 0) return big0;
+ BigInteger dividend = big1.shiftLeft(log_scale_factor);
+ BigInteger scaled_divisor = op.get_appr(prec_needed);
+ BigInteger abs_scaled_divisor = scaled_divisor.abs();
+ BigInteger adj_dividend = dividend.add(
+ abs_scaled_divisor.shiftRight(1));
+ // Adjustment so that final result is rounded.
+ BigInteger result = adj_dividend.divide(abs_scaled_divisor);
+ if (scaled_divisor.signum() < 0) {
+ return result.negate();
+ } else {
+ return result;
+ }
}
}
@@ -993,37 +993,37 @@ class prescaled_exp_CR extends CR {
CR op;
prescaled_exp_CR(CR x) { op = x; }
protected BigInteger approximate(int p) {
- if (p >= 1) return big0;
- int iterations_needed = -p/2 + 2; // conservative estimate > 0.
- // Claim: each intermediate term is accurate
- // to 2*2^calc_precision.
- // Total rounding error in series computation is
- // 2*iterations_needed*2^calc_precision,
- // exclusive of error in op.
- int calc_precision = p - bound_log2(2*iterations_needed)
- - 4; // for error in op, truncation.
- int op_prec = p - 3;
- BigInteger op_appr = op.get_appr(op_prec);
- // Error in argument results in error of < 3/8 ulp.
- // Sum of term eval. rounding error is < 1/16 ulp.
- // Series truncation error < 1/16 ulp.
- // Final rounding error is <= 1/2 ulp.
- // Thus final error is < 1 ulp.
- BigInteger scaled_1 = big1.shiftLeft(-calc_precision);
- BigInteger current_term = scaled_1;
- BigInteger current_sum = scaled_1;
- int n = 0;
- BigInteger max_trunc_error =
- big1.shiftLeft(p - 4 - calc_precision);
- while (current_term.abs().compareTo(max_trunc_error) >= 0) {
- if (Thread.interrupted() || please_stop) throw new AbortedError();
- n += 1;
- /* current_term = current_term * op / n */
- current_term = scale(current_term.multiply(op_appr), op_prec);
- current_term = current_term.divide(BigInteger.valueOf(n));
- current_sum = current_sum.add(current_term);
- }
- return scale(current_sum, calc_precision - p);
+ if (p >= 1) return big0;
+ int iterations_needed = -p/2 + 2; // conservative estimate > 0.
+ // Claim: each intermediate term is accurate
+ // to 2*2^calc_precision.
+ // Total rounding error in series computation is
+ // 2*iterations_needed*2^calc_precision,
+ // exclusive of error in op.
+ int calc_precision = p - bound_log2(2*iterations_needed)
+ - 4; // for error in op, truncation.
+ int op_prec = p - 3;
+ BigInteger op_appr = op.get_appr(op_prec);
+ // Error in argument results in error of < 3/8 ulp.
+ // Sum of term eval. rounding error is < 1/16 ulp.
+ // Series truncation error < 1/16 ulp.
+ // Final rounding error is <= 1/2 ulp.
+ // Thus final error is < 1 ulp.
+ BigInteger scaled_1 = big1.shiftLeft(-calc_precision);
+ BigInteger current_term = scaled_1;
+ BigInteger current_sum = scaled_1;
+ int n = 0;
+ BigInteger max_trunc_error =
+ big1.shiftLeft(p - 4 - calc_precision);
+ while (current_term.abs().compareTo(max_trunc_error) >= 0) {
+ if (Thread.interrupted() || please_stop) throw new AbortedError();
+ n += 1;
+ /* current_term = current_term * op / n */
+ current_term = scale(current_term.multiply(op_appr), op_prec);
+ current_term = current_term.divide(BigInteger.valueOf(n));
+ current_sum = current_sum.add(current_term);
+ }
+ return scale(current_sum, calc_precision - p);
}
}
@@ -1032,44 +1032,44 @@ class prescaled_exp_CR extends CR {
class prescaled_cos_CR extends slow_CR {
CR op;
prescaled_cos_CR(CR x) {
- op = x;
+ op = x;
}
protected BigInteger approximate(int p) {
- if (p >= 1) return big0;
- int iterations_needed = -p/2 + 4; // conservative estimate > 0.
- // Claim: each intermediate term is accurate
- // to 2*2^calc_precision.
- // Total rounding error in series computation is
- // 2*iterations_needed*2^calc_precision,
- // exclusive of error in op.
- int calc_precision = p - bound_log2(2*iterations_needed)
- - 4; // for error in op, truncation.
- int op_prec = p - 2;
- BigInteger op_appr = op.get_appr(op_prec);
- // Error in argument results in error of < 1/4 ulp.
- // Cumulative arithmetic rounding error is < 1/16 ulp.
- // Series truncation error < 1/16 ulp.
- // Final rounding error is <= 1/2 ulp.
- // Thus final error is < 1 ulp.
- BigInteger current_term;
- int n;
- BigInteger max_trunc_error =
- big1.shiftLeft(p - 4 - calc_precision);
- n = 0;
- current_term = big1.shiftLeft(-calc_precision);
- BigInteger current_sum = current_term;
- while (current_term.abs().compareTo(max_trunc_error) >= 0) {
- if (Thread.interrupted() || please_stop) throw new AbortedError();
- n += 2;
- /* current_term = - current_term * op * op / n * (n - 1) */
- current_term = scale(current_term.multiply(op_appr), op_prec);
- current_term = scale(current_term.multiply(op_appr), op_prec);
- BigInteger divisor = BigInteger.valueOf(-n)
- .multiply(BigInteger.valueOf(n-1));
- current_term = current_term.divide(divisor);
- current_sum = current_sum.add(current_term);
- }
- return scale(current_sum, calc_precision - p);
+ if (p >= 1) return big0;
+ int iterations_needed = -p/2 + 4; // conservative estimate > 0.
+ // Claim: each intermediate term is accurate
+ // to 2*2^calc_precision.
+ // Total rounding error in series computation is
+ // 2*iterations_needed*2^calc_precision,
+ // exclusive of error in op.
+ int calc_precision = p - bound_log2(2*iterations_needed)
+ - 4; // for error in op, truncation.
+ int op_prec = p - 2;
+ BigInteger op_appr = op.get_appr(op_prec);
+ // Error in argument results in error of < 1/4 ulp.
+ // Cumulative arithmetic rounding error is < 1/16 ulp.
+ // Series truncation error < 1/16 ulp.
+ // Final rounding error is <= 1/2 ulp.
+ // Thus final error is < 1 ulp.
+ BigInteger current_term;
+ int n;
+ BigInteger max_trunc_error =
+ big1.shiftLeft(p - 4 - calc_precision);
+ n = 0;
+ current_term = big1.shiftLeft(-calc_precision);
+ BigInteger current_sum = current_term;
+ while (current_term.abs().compareTo(max_trunc_error) >= 0) {
+ if (Thread.interrupted() || please_stop) throw new AbortedError();
+ n += 2;
+ /* current_term = - current_term * op * op / n * (n - 1) */
+ current_term = scale(current_term.multiply(op_appr), op_prec);
+ current_term = scale(current_term.multiply(op_appr), op_prec);
+ BigInteger divisor = BigInteger.valueOf(-n)
+ .multiply(BigInteger.valueOf(n-1));
+ current_term = current_term.divide(divisor);
+ current_sum = current_sum.add(current_term);
+ }
+ return scale(current_sum, calc_precision - p);
}
}
@@ -1080,41 +1080,41 @@ class integral_atan_CR extends slow_CR {
int op;
integral_atan_CR(int x) { op = x; }
protected BigInteger approximate(int p) {
- if (p >= 1) return big0;
- int iterations_needed = -p/2 + 2; // conservative estimate > 0.
- // Claim: each intermediate term is accurate
- // to 2*base^calc_precision.
- // Total rounding error in series computation is
- // 2*iterations_needed*base^calc_precision,
- // exclusive of error in op.
- int calc_precision = p - bound_log2(2*iterations_needed)
- - 2; // for error in op, truncation.
- // Error in argument results in error of < 3/8 ulp.
- // Cumulative arithmetic rounding error is < 1/4 ulp.
- // Series truncation error < 1/4 ulp.
- // Final rounding error is <= 1/2 ulp.
- // Thus final error is < 1 ulp.
- BigInteger scaled_1 = big1.shiftLeft(-calc_precision);
+ if (p >= 1) return big0;
+ int iterations_needed = -p/2 + 2; // conservative estimate > 0.
+ // Claim: each intermediate term is accurate
+ // to 2*base^calc_precision.
+ // Total rounding error in series computation is
+ // 2*iterations_needed*base^calc_precision,
+ // exclusive of error in op.
+ int calc_precision = p - bound_log2(2*iterations_needed)
+ - 2; // for error in op, truncation.
+ // Error in argument results in error of < 3/8 ulp.
+ // Cumulative arithmetic rounding error is < 1/4 ulp.
+ // Series truncation error < 1/4 ulp.
+ // Final rounding error is <= 1/2 ulp.
+ // Thus final error is < 1 ulp.
+ BigInteger scaled_1 = big1.shiftLeft(-calc_precision);
BigInteger big_op = BigInteger.valueOf(op);
BigInteger big_op_squared = BigInteger.valueOf(op*op);
- BigInteger op_inverse = scaled_1.divide(big_op);
- BigInteger current_power = op_inverse;
- BigInteger current_term = op_inverse;
- BigInteger current_sum = op_inverse;
- int current_sign = 1;
- int n = 1;
- BigInteger max_trunc_error =
- big1.shiftLeft(p - 2 - calc_precision);
- while (current_term.abs().compareTo(max_trunc_error) >= 0) {
- if (Thread.interrupted() || please_stop) throw new AbortedError();
- n += 2;
- current_power = current_power.divide(big_op_squared);
- current_sign = -current_sign;
- current_term =
- current_power.divide(BigInteger.valueOf(current_sign*n));
+ BigInteger op_inverse = scaled_1.divide(big_op);
+ BigInteger current_power = op_inverse;
+ BigInteger current_term = op_inverse;
+ BigInteger current_sum = op_inverse;
+ int current_sign = 1;
+ int n = 1;
+ BigInteger max_trunc_error =
+ big1.shiftLeft(p - 2 - calc_precision);
+ while (current_term.abs().compareTo(max_trunc_error) >= 0) {
+ if (Thread.interrupted() || please_stop) throw new AbortedError();
+ n += 2;
+ current_power = current_power.divide(big_op_squared);
+ current_sign = -current_sign;
+ current_term =
+ current_power.divide(BigInteger.valueOf(current_sign*n));
current_sum = current_sum.add(current_term);
- }
- return scale(current_sum, calc_precision - p);
+ }
+ return scale(current_sum, calc_precision - p);
}
}
@@ -1122,90 +1122,90 @@ class integral_atan_CR extends slow_CR {
class prescaled_ln_CR extends slow_CR {
CR op;
prescaled_ln_CR(CR x) { op = x; }
- // Compute an approximation of ln(1+x) to precision
- // prec. This assumes |x| < 1/2.
- // It uses a Taylor series expansion.
- // Unfortunately there appears to be no way to take
- // advantage of old information.
- // Note: this is known to be a bad algorithm for
+ // Compute an approximation of ln(1+x) to precision
+ // prec. This assumes |x| < 1/2.
+ // It uses a Taylor series expansion.
+ // Unfortunately there appears to be no way to take
+ // advantage of old information.
+ // Note: this is known to be a bad algorithm for
// floating point. Unfortunately, other alternatives
- // appear to require precomputed tabular information.
+ // appear to require precomputed tabular information.
protected BigInteger approximate(int p) {
- if (p >= 0) return big0;
- int iterations_needed = -p; // conservative estimate > 0.
- // Claim: each intermediate term is accurate
- // to 2*2^calc_precision. Total error is
- // 2*iterations_needed*2^calc_precision
- // exclusive of error in op.
- int calc_precision = p - bound_log2(2*iterations_needed)
- - 4; // for error in op, truncation.
- int op_prec = p - 3;
- BigInteger op_appr = op.get_appr(op_prec);
- // Error analysis as for exponential.
- BigInteger scaled_1 = big1.shiftLeft(-calc_precision);
- BigInteger x_nth = scale(op_appr, op_prec - calc_precision);
- BigInteger current_term = x_nth; // x**n
- BigInteger current_sum = current_term;
- int n = 1;
- int current_sign = 1; // (-1)^(n-1)
- BigInteger max_trunc_error =
- big1.shiftLeft(p - 4 - calc_precision);
- while (current_term.abs().compareTo(max_trunc_error) >= 0) {
- if (Thread.interrupted() || please_stop) throw new AbortedError();
- n += 1;
+ if (p >= 0) return big0;
+ int iterations_needed = -p; // conservative estimate > 0.
+ // Claim: each intermediate term is accurate
+ // to 2*2^calc_precision. Total error is
+ // 2*iterations_needed*2^calc_precision
+ // exclusive of error in op.
+ int calc_precision = p - bound_log2(2*iterations_needed)
+ - 4; // for error in op, truncation.
+ int op_prec = p - 3;
+ BigInteger op_appr = op.get_appr(op_prec);
+ // Error analysis as for exponential.
+ BigInteger scaled_1 = big1.shiftLeft(-calc_precision);
+ BigInteger x_nth = scale(op_appr, op_prec - calc_precision);
+ BigInteger current_term = x_nth; // x**n
+ BigInteger current_sum = current_term;
+ int n = 1;
+ int current_sign = 1; // (-1)^(n-1)
+ BigInteger max_trunc_error =
+ big1.shiftLeft(p - 4 - calc_precision);
+ while (current_term.abs().compareTo(max_trunc_error) >= 0) {
+ if (Thread.interrupted() || please_stop) throw new AbortedError();
+ n += 1;
current_sign = -current_sign;
- x_nth = scale(x_nth.multiply(op_appr), op_prec);
- current_term = x_nth.divide(BigInteger.valueOf(n * current_sign));
- // x**n / (n * (-1)**(n-1))
- current_sum = current_sum.add(current_term);
- }
- return scale(current_sum, calc_precision - p);
+ x_nth = scale(x_nth.multiply(op_appr), op_prec);
+ current_term = x_nth.divide(BigInteger.valueOf(n * current_sign));
+ // x**n / (n * (-1)**(n-1))
+ current_sum = current_sum.add(current_term);
+ }
+ return scale(current_sum, calc_precision - p);
}
}
class sqrt_CR extends CR {
CR op;
sqrt_CR(CR x) { op = x; }
- final int fp_prec = 50; // Conservative estimate of number of
- // significant bits in double precision
- // computation.
+ final int fp_prec = 50; // Conservative estimate of number of
+ // significant bits in double precision
+ // computation.
final int fp_op_prec = 60;
protected BigInteger approximate(int p) {
- int max_prec_needed = 2*p - 1;
- int msd = op.msd(max_prec_needed);
- if (msd <= max_prec_needed) return big0;
- int result_msd = msd/2; // +- 1
- int result_digits = result_msd - p; // +- 2
- if (result_digits > fp_prec) {
- // Compute less precise approximation and use a Newton iter.
- int appr_digits = result_digits/2 + 6;
- // This should be conservative. Is fewer enough?
- int appr_prec = result_msd - appr_digits;
- BigInteger last_appr = get_appr(appr_prec);
- int prod_prec = 2*appr_prec;
- BigInteger op_appr = op.get_appr(prod_prec);
- // Slightly fewer might be enough;
- // Compute (last_appr * last_appr + op_appr)/(last_appr/2)
- // while adjusting the scaling to make everything work
- BigInteger prod_prec_scaled_numerator =
- last_appr.multiply(last_appr).add(op_appr);
- BigInteger scaled_numerator =
- scale(prod_prec_scaled_numerator, appr_prec - p);
- BigInteger shifted_result = scaled_numerator.divide(last_appr);
- return shifted_result.add(big1).shiftRight(1);
- } else {
- // Use a double precision floating point approximation.
- // Make sure all precisions are even
- int op_prec = (msd - fp_op_prec) & ~1;
- int working_prec = op_prec - fp_op_prec;
- BigInteger scaled_bi_appr = op.get_appr(op_prec)
- .shiftLeft(fp_op_prec);
- double scaled_appr = scaled_bi_appr.doubleValue();
- if (scaled_appr < 0.0) throw new ArithmeticException();
- double scaled_fp_sqrt = Math.sqrt(scaled_appr);
- BigInteger scaled_sqrt = BigInteger.valueOf((long)scaled_fp_sqrt);
- int shift_count = working_prec/2 - p;
- return shift(scaled_sqrt, shift_count);
- }
+ int max_prec_needed = 2*p - 1;
+ int msd = op.msd(max_prec_needed);
+ if (msd <= max_prec_needed) return big0;
+ int result_msd = msd/2; // +- 1
+ int result_digits = result_msd - p; // +- 2
+ if (result_digits > fp_prec) {
+ // Compute less precise approximation and use a Newton iter.
+ int appr_digits = result_digits/2 + 6;
+ // This should be conservative. Is fewer enough?
+ int appr_prec = result_msd - appr_digits;
+ BigInteger last_appr = get_appr(appr_prec);
+ int prod_prec = 2*appr_prec;
+ BigInteger op_appr = op.get_appr(prod_prec);
+ // Slightly fewer might be enough;
+ // Compute (last_appr * last_appr + op_appr)/(last_appr/2)
+ // while adjusting the scaling to make everything work
+ BigInteger prod_prec_scaled_numerator =
+ last_appr.multiply(last_appr).add(op_appr);
+ BigInteger scaled_numerator =
+ scale(prod_prec_scaled_numerator, appr_prec - p);
+ BigInteger shifted_result = scaled_numerator.divide(last_appr);
+ return shifted_result.add(big1).shiftRight(1);
+ } else {
+ // Use a double precision floating point approximation.
+ // Make sure all precisions are even
+ int op_prec = (msd - fp_op_prec) & ~1;
+ int working_prec = op_prec - fp_op_prec;
+ BigInteger scaled_bi_appr = op.get_appr(op_prec)
+ .shiftLeft(fp_op_prec);
+ double scaled_appr = scaled_bi_appr.doubleValue();
+ if (scaled_appr < 0.0) throw new ArithmeticException();
+ double scaled_fp_sqrt = Math.sqrt(scaled_appr);
+ BigInteger scaled_sqrt = BigInteger.valueOf((long)scaled_fp_sqrt);
+ int shift_count = working_prec/2 - p;
+ return shift(scaled_sqrt, shift_count);
+ }
}
}
diff --git a/src/CRCalc.java b/src/CRCalc.java
deleted file mode 100644
index 3085f18..0000000
--- a/src/CRCalc.java
+++ /dev/null
@@ -1,1605 +0,0 @@
-// Copyright © 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED
-//
-// Permission is granted free of charge to copy, modify, use and distribute
-// this software provided you include the entirety of this notice in all
-// copies made.
-//
-// THIS SOFTWARE IS PROVIDED ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY
-// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
-// WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT
-// FOR A PARTICULAR PURPOSE OR NON-INFRINGING. SGI ASSUMES NO RISK AS TO THE
-// QUALITY AND PERFORMANCE OF THE SOFTWARE. SHOULD THE SOFTWARE PROVE
-// DEFECTIVE IN ANY RESPECT, SGI ASSUMES NO COST OR LIABILITY FOR ANY
-// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES
-// AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS
-// AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
-//
-// UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING,
-// WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY), CONTRACT, OR
-// OTHERWISE, SHALL SGI BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL,
-// INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER WITH RESPECT TO THE
-// SOFTWARE INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK
-// STOPPAGE, LOSS OF DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL
-// OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SGI SHALL HAVE BEEN INFORMED OF
-// THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT
-// APPLY TO LIABILITY RESULTING FROM SGI's NEGLIGENCE TO THE EXTENT APPLICABLE
-// LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
-// EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT
-// EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
-//
-// These license terms shall be governed by and construed in accordance with
-// the laws of the United States and the State of California as applied to
-// agreements entered into and to be performed entirely within California
-// between California residents. Any litigation relating to these license
-// terms shall be subject to the exclusive jurisdiction of the Federal Courts
-// of the Northern District of California (or, absent subject matter
-// jurisdiction in such courts, the courts of the State of California), with
-// venue lying exclusively in Santa Clara County, California.
-
-// This is version 0.5
-// Version 0.4 was the original version distributed by SGI.
-// Version 0.5 adds a test for tan(<odd multiple of pi>)
-// (Suggested by Dan Grayson, implemented by Hans_Boehm@hp.com)
-
-import java.applet.*;
-import java.awt.*;
-import java.awt.event.*;
-import java.awt.datatransfer.*;
-import com.sgi.math.CR;
-import com.sgi.math.UnaryCRFunction;
-import com.sgi.math.AbortedError;
-import com.sgi.math.PrecisionOverflowError;
-import java.math.BigInteger;
-
-// A message window with an OK or YES/NO prompt.
-class calc_msg extends Frame implements ActionListener {
- Button ok_button;
- Button yes_button;
- Button no_button;
- Dialog d;
- Panel p;
- Component t; // Widget containing test
- static final int label_limit = 50;
- boolean ask;
- boolean answer;
- boolean done;
-
- calc_msg(String S, boolean a) {
- ask = a;
- int len = S.length();
- done = false;
- d = new Dialog(this, "CRCalc information");
- if (len > label_limit) {
- t = new TextArea(S);
- } else {
- t = new Label(S);
- }
- if (ask) {
- yes_button = new Button("YES");
- yes_button.addActionListener(this);
- no_button = new Button("NO");
- no_button.addActionListener(this);
- } else {
- ok_button = new Button("OK");
- ok_button.addActionListener(this);
- }
- p = new Panel();
- p.setLayout(new GridLayout(1, 3));
- if (ask) {
- p.add(yes_button);
- } else {
- p.add(new Label());
- }
- p.add(new Label());
- if (ask) {
- p.add(no_button);
- } else {
- p.add(ok_button);
- }
- d.add("North", t);
- d.add("South", p);
- if (len > label_limit) {
- d.setSize(520,300);
- } else {
- d.setSize(400, 100);
- }
- d.show();
- }
- public synchronized void actionPerformed(ActionEvent e) {
- answer = (e.getSource() == yes_button);
- done = true;
- dispose();
- notify();
- }
- public synchronized boolean get_answer() {
- while (!done) {
- try {
- wait();
- } catch(InterruptedException e) { return false; }
- }
- return answer;
- }
-}
-
-// The queue of commands waiting to be executed. Used to communicate
-// with the worker thread.
-class command_queue_entry {
- char command;
- command_queue_entry next;
- command_queue_entry(char c) {
- command = c;
- next = null;
- }
-}
-
-// Queue of commands waiting to be executed by the worker thread.
-// Duplicate refresh commands are quietly dropped to improve performance
-// on slower machines.
-class command_queue {
- static final char noop_command = (char)0;
- static final char refresh_command = ',';
- volatile boolean please_exit;
- command_queue_entry first;
- command_queue_entry last;
- command_queue() {
- first = null;
- last = null;
- }
- synchronized void add(char c) {
- command_queue_entry new_last = new command_queue_entry(c);
- if (refresh_command == c) {
- // Eliminate duplicate refresh commands
- for (command_queue_entry p = first; p != null; p = p.next) {
- if (p.command == refresh_command) {
- p.command = noop_command;
- }
- }
- }
- if (null == first) {
- first = new_last;
- last = new_last;
- } else {
- last.next = new_last;
- last = new_last;
- }
- notify();
- }
- synchronized char get() {
- char result;
- do {
- while (null == first) {
- try {
- wait(1000);
- } catch (InterruptedException e) {return noop_command;}
- if (please_exit) { return noop_command; }
- }
- result = first.command;
- first = first.next;
- if (null == first) last = null;
- } while (result == noop_command);
- return result;
- }
-}
-
-// This is a gross hack to force most VMs that don't normally timeslice to
-// do so. Without timeslicing a stop button push will never be processed.
-// (Actually, it should be, since the worker runs at lower priority.
-// Empirically, that doesn't seem to matter much, probably due to awt
-// issues.) Unnessary for VMs that timeslice correctly, but we can't
-// easily identify those.
-class time_slicer implements Runnable {
- volatile boolean please_exit;
-
- public void run() {
- try {
- for (;;) {
- if (please_exit) break;
- Thread.sleep(100);
- }
- } catch(InterruptedException e) {}
- }
-}
-
-// Radian to/from degree conversion functions.
-class to_degrees_class extends UnaryCRFunction {
- CR multiplier = CR.valueOf(180).divide(CR.PI);
- public CR execute(CR x) {
- return multiplier.multiply(x);
- }
-}
-
-class from_degrees_class extends UnaryCRFunction {
- CR multiplier = CR.PI.divide(CR.valueOf(180));
- public CR execute(CR x) {
- return multiplier.multiply(x);
- }
-}
-
-public class CRCalc extends Applet
-implements AdjustmentListener, ActionListener,
- KeyListener, TextListener, ItemListener, Runnable {
-
- static final String help_text =
- "This is a calculator that operates on \"exact\" real numbers.\n" +
- "More precisely, numbers are represented internally so that\n" +
- "they can be evaluated to any needed precision. As a\n" +
- "result, the displayed numbers are accurate to an error\n" +
- "of strictly less than 1 digit in the last displayed\n" +
- "digit, no matter how the number was computed. Subexpressions\n" +
- "are evaluated to enough precision to ensure that cumulative\n" +
- "rounding errors remain invisible.\n" +
- "\n" +
- "OPERATION:\n" +
- "The calculator uses \"reverse Polish notation\".\n" +
- "To compute 1 + 2, enter <1><enter><2><+>\n" +
- "Digits may either be typed into the main display window\n" +
- "from the keyboard, or may be entered with the calculator\n" +
- "buttons. The operation buttons also have keyboard\n" +
- "equivalents, which will appear in the history window near\n" +
- "the bottom of the calculator. Additionally, either <space>\n" +
- "or <enter> a.k.a. <return> may be used as <enter> equivalents.\n\n" +
- "The main display window displays all values on the current\n" +
- "operand stack. Operations apply to the the value(s) nearest\n" +
- "the bottom of the screen. To add a long sequence of numbers,\n" +
- "it is often most convenient to enter all of them, separated\n" +
- "by <enter>, and then add them by repeatedly pushing <+>.\n\n" +
- "The history window at the bottom of the calculator can be\n" +
- "useful for reviewing past operations, or reexeuting them.\n\n" +
- "The small text window under the main display gives the place\n" +
- "value of the least significant displayed digit. If it\n" +
- "displays -100, then right most digit is the 100th digit to the\n" +
- "right of the decimal point, with place value of 10^(-100).\n" +
- "The display can be shifted right or left by either editing the\n" +
- "number in the small window, or by using the adjacent scroll bar.\n" +
- "\n" +
- "CONTROL BUTTONS:\n" +
- "The calculator includes a column of six control buttons.\n" +
- "One of them is the \"HELP\" button that generated this text.\n" +
- "The others are:\n" +
- "STOP:\taborts the current computation. This may cause\n" +
- "\tsome partial results to be lost (see \"replay\"). It\n" +
- "\tis quite easy to start the calculator on a computation\n" +
- "\tthat will never finish, or finish only when it runs out\n" +
- "\tmemory. The simplest way to do this is to divide by 0.\n" +
- "\tIn this case you may need to use the STOP button. Many\n" +
- "\toperations will warn you if it appears likely that you \n" +
- "\twill need to use the stop button. It is difficult for\n" +
- "\tthe calculator to determine whether an arbitrarily\n" +
- "\tcomputed number is exactly zero. It doesn't even try.\n" +
- "\t(This is undecidable for arbitrary constructive reals.\n" +
- "\tIt is probably just impractically expensive for the\n" +
- "\toperations provided by the calculator.\n" +
- "\tThe stop button also serves as an indication that a\n" +
- "\tcalculation is in progress. A lower case \"stop\" label\n" +
- "\ton the button indicates the calculator is idle. An\n" +
- "\tupper case \"STOP!\" label means that a caclulation is\n" +
- "\tin progress, and the button is functional.\n" +
- "set prec: Set the displayed precision (place value of\n" +
- "\tleast displayed digit) to be the number on top of\n" +
- "\tstack, and pop the stack. Entering -10 and then clicking\n" +
- "\t<set prec> will display 10 digits to the right of the\n" +
- "\tdecimal point. This is an alternative to the scroll bar\n" +
- "\tand scroll window.\n" +
- "replay: Reexecutes the commands the selected in the\n" +
- "\thistory window. Select the text before pressing the button.\n" +
- "\tSince the history window is editable, on many systems this\n" +
- "\talso gives a way to copy numbers into the calculator: First\n" +
- "\tpaste the number into the history window, then select it,\n" +
- "\tand press replay.\n" +
- "write: Write the top of stack to the Java console. The\n" +
- "\tnumber is written out to the current precision. Digits\n" +
- "\tto the left of the display window are included. (Many\n" +
- "\tbrowsers will allow the result from the Java console to\n" +
- "\tbe displayed and pasted elsewhere. Direct clipboard access\n" +
- "\tfrom Java applets is normally disallowed for security\n" +
- "\treasons.)\n" +
- "base 16: Switches to base 16 mode if pushed or checked.\n"+
- "\tAffects both input and display. To convert\n" +
- "\tbetween bases, enter the number, then switch.\n" +
- "\tHexadecimal digits between \"a\" and \"f\" must be entered\n" +
- "\twith the keyboard and input focus on the display window\n" +
- "degrees: Alters the behavior of the trignonometric\n" +
- "\tfunctions to measure angles in either degrees or radians\n" +
- "\n" +
- "EXAMPLES:\n" +
- "Ramanujan's number (exp(pi*sqrt(163))) is entered as\n" +
- "<pi><1><6><3><sqrt><*><exp>\n" +
- "or from the keyboard as \"p163r*x\"\n" +
- "Note that the result is not an integer.\n" +
- "\n" +
- "To see the difference between this and other calculators, try\n" +
- "ln(pi + exp(-234) - pi), which can be entered as\n" +
- "<pi><2><3><4><+/-><exp><+><pi><-><ln>\n"
- ;
- static final int stack_size = 300;
- int display_width;
- int display_char_width;
- final int initial_prec = -22;
- static final int max_history_len = 200;
- static final BigInteger big0 = BigInteger.valueOf(0);
- static final BigInteger big10 = BigInteger.valueOf(10);
- static final BigInteger big16 = BigInteger.valueOf(16);
- static final to_degrees_class to_degrees = new to_degrees_class();
- static final from_degrees_class from_degrees = new from_degrees_class();
-
- /* This thread actually executes operations, so that we can stop */
- /* it if necessary. */
- Thread worker;
-
- /* Extra high priority thread to force time slicing. */
- time_slicer ts;
- Thread ts_thread;
-
- /* Calculator state, updated only by worker thread. */
- CR stack[] = new CR[stack_size]; // top at higher indicees.
- int stack_ptr; // number of valid entries.
- CR mem = CR.valueOf(0); // memory contents.
- int current_prec; // Weight of least displayed digit
- // is 10**current_prec.
- // This is a final array of one element
- // so that it can be changed from an
- // inner class.
- BigInteger current_entry; // Number entered so far if decimal
- // point had not been entered.
- boolean point_entered; // Was decimal point entered?
- int fraction_digits; // number of digits to the right of
- // decimal point.
- int digits_entered; // Count of number of digits entered.
- int current_base; // Entry and display radix.
- boolean degree_mode; // Currently using degrees as angle
- // measure.
- // Current angle conversion function.
- // In degree mode these perform the appropriate scaling.
- UnaryCRFunction input_converter;
- UnaryCRFunction output_converter;
-
- BigInteger current_big_base;
- String current_entry_string = new String();
- String history_contents = new String();
-
- // Queue of commands to be executed by worker.
- command_queue cq;
-
- // Widgets that make up the calculator UI
- TextArea display;
- final Scrollbar prec_scroll = new Scrollbar(Scrollbar.HORIZONTAL);
- final TextField prec_window = new TextField("", 10);
- TextArea history;
- Panel keypad;
- Panel control_panel;
- Panel keypanel; // The above two combined, so they stay together.
- Panel prec_scroll_panel;
- Button add_button;
- Button multiply_button;
- Button subtract_button;
- Button divide_button;
- Button power_button;
- Button dot_button;
- Button enter_button;
- Button negate_button;
- Button inverse_button;
- Button sqrt_button;
- Button exp_button;
- Button ln_button;
- Button pi_button;
- Button digit_button[] = new Button[10];
- Button sin_button;
- Button cos_button;
- Button tan_button;
- Button asin_button;
- Button acos_button;
- Button atan_button;
- Button help_button;
- Button stop_button;
- Button xchg_button;
- Button clear_button;
- Button clear_all_button;
- Button copy_button;
- Button store_button;
- Button recall_button;
- Checkbox base_box;
- Button replay_button;
- Button set_prec_button;
- // Button paste_button;
- Button write_button;
- Checkbox degree_box;
-
- // A helper function for refresh
- // Generate a String containing n blanks.
- private static String blanks(int n) {
- char[] a = new char[n];
- for (int i = 0; i < n; ++i) {
- a[i] = ' ';
- }
- return new String(a);
- }
-
- static final int extra_prec = 15; // Extra digits generated and then
- // discarded. This makes it unlikely
- // that digits flip-flop as more
- // precision is requested.
-
- // Recompute the display after a stack or precision change.
- // Should run only in worker thread, since it may fail to terminate.
- void refresh() {
- String display_contents = new String();
-
- for (int i = 0; i < stack_ptr; ++i) {
- int convert_prec = -current_prec + extra_prec;
- CR current_entry = stack[i];
- if (convert_prec < 0) {
- BigInteger scale = current_big_base.pow(-convert_prec);
- CR cr_scale = CR.valueOf(scale);
- current_entry = current_entry.divide(cr_scale);
- convert_prec = 0;
- }
- String this_entry = current_entry.toString(convert_prec,
- current_base);
- int len = this_entry.length();
- if (len <= extra_prec) {
- // Not this long
- this_entry = blanks(display_char_width - 3) + "-->";
- } else {
- int end_char = len - extra_prec;
- if (end_char > display_char_width) {
- this_entry = this_entry.substring(end_char
- - display_char_width,
- end_char);
- } else {
- this_entry = blanks(display_char_width - end_char)
- + this_entry.substring(0, end_char);
- }
- }
- if (i != 0) display_contents += "\n";
- display_contents += this_entry;
- }
- if (stack_ptr != 0) display_contents += "\n";
- if (digits_entered > 0) {
- display_contents += current_entry_string;
- }
- display.setText(display_contents);
- display.setCaretPosition(display_contents.length());
- }
-
- void add_history_char(char c)
- {
- add_history_string(String.valueOf(c));
- }
-
- void add_history_string(String s)
- {
- String history_contents = history.getText() + s;
- int len = history_contents.length();
- if (len > max_history_len) {
- history_contents = history_contents.substring(
- len - max_history_len);
- }
- history.setText(history_contents);
- history.setCaretPosition(history_contents.length());
- }
-
- // Clear the current partial entry.
- void clear_current_entry() {
- current_entry = big0;
- current_entry_string = "";
- point_entered = false;
- fraction_digits = 0;
- digits_entered = 0;
- }
-
- // Remove the last typed character.
- void delete_last_char() {
- if (point_entered) {
- if (fraction_digits == 0) {
- point_entered = false;
- } else {
- --fraction_digits;
- current_entry = current_entry.divide(current_big_base);
- --digits_entered;
- }
- } else {
- current_entry = current_entry.divide(current_big_base);
- --digits_entered;
- }
- int len = current_entry_string.length();
- current_entry_string = current_entry_string.substring(0, len-1);
- }
-
- // Action when "clear entry" button is pushed.
- void clear_entry() {
- if (digits_entered == 0 && stack_ptr > 0) {
- pop();
- } else {
- clear_current_entry();
- }
- }
-
- void clear() {
- clear_entry();
- stack_ptr = 0;
- }
-
- void msg(String S) {
- new calc_msg(S, false);
- }
-
- // Display warning or error message.
- void warn(String S) {
- this.getToolkit().beep();
- msg(S);
- }
-
- // Ask the user a question.
- boolean ask(String S) {
- this.getToolkit().beep();
- calc_msg m = new calc_msg(S, true);
- return m.get_answer();
- }
-
- void push(CR x) {
- if (stack_ptr == stack_size) {
- warn("Stack_overflow");
- } else {
- stack[stack_ptr] = x;
- ++stack_ptr;
- }
- }
-
- void pop() {
- if (stack_ptr > 0) --stack_ptr;
- stack[stack_ptr] = null; // only a space optimization.
- }
-
- boolean check_unary() {
- if (digits_entered > 0 || point_entered) enter();
- if (stack_ptr < 1) {
- warn("No argument for unary operation");
- return false;
- } else {
- return true;
- }
- }
-
- boolean check_binary() {
- if (digits_entered > 0 || point_entered) enter();
- if (stack_ptr < 2) {
- warn("Too few arguments for binary operation");
- return false;
- } else {
- return true;
- }
- }
-
- void finish_binary(CR result, char h)
- {
- pop(); pop();
- push(result);
- add_history_char(h);
- refresh();
- }
-
- void do_add() {
- if (!check_binary()) return;
- CR op2 = stack[stack_ptr-1];
- CR op1 = stack[stack_ptr-2];
- CR result = op1.add(op2);
- finish_binary(result, '+');
- }
-
- void do_multiply() {
- if (!check_binary()) return;
- CR op2 = stack[stack_ptr-1];
- CR op1 = stack[stack_ptr-2];
- CR result = op1.multiply(op2);
- finish_binary(result, '*');
- }
-
- void do_subtract() {
- if (!check_binary()) return;
- CR op2 = stack[stack_ptr-1];
- CR op1 = stack[stack_ptr-2];
- CR result = op1.subtract(op2);
- finish_binary(result, '-');
- }
-
- void do_divide() {
- if (!check_binary()) return;
- CR op2 = stack[stack_ptr-1];
- CR op1 = stack[stack_ptr-2];
- CR result = op1.divide(op2);
- finish_binary(result, '/');
- }
-
- void do_power() {
- CR result;
- if (!check_binary()) return;
- CR op2 = stack[stack_ptr-1];
- CR op1 = stack[stack_ptr-2];
- BigInteger int1 = op1.get_appr(0);
- BigInteger int2 = op2.get_appr(0);
- result = op1.ln().multiply(op2).exp();
- finish_binary(result, '^');
- }
-
-
- void do_exchange() {
- if (!check_binary()) return;
- CR tmp = stack[stack_ptr-1];
- stack[stack_ptr-1] = stack[stack_ptr-2];
- stack[stack_ptr-2] = tmp;
- add_history_char('i');
- refresh();
- }
-
- void do_unary(UnaryCRFunction f, char c) {
- if (!check_unary()) return;
- stack[stack_ptr - 1] = f.execute(stack[stack_ptr - 1]);
- add_history_char(c);
- refresh();
- }
-
- void do_pi() {
- if (digits_entered > 0 || point_entered) enter();
- push(CR.PI);
- add_history_char('p');
- refresh();
- }
-
- void do_copy() {
- if (!check_unary()) return;
- push(stack[stack_ptr - 1]);
- add_history_char('q');
- refresh();
- }
-
- void do_store() {
- if (!check_unary()) return;
- mem = stack[stack_ptr - 1];
- add_history_char('=');
- refresh(); // May have done an implicit "enter"
- }
-
- void do_recall() {
- if (digits_entered > 0 || point_entered) enter();
- push(mem);
- add_history_char('g');
- refresh();
- }
-
- void add_digit(int d) {
- ++digits_entered;
- if (point_entered) {
- ++fraction_digits;
- }
- current_entry = current_entry.multiply(current_big_base);
- current_entry = current_entry.add(BigInteger.valueOf(d));
- if (d <= 9) {
- current_entry_string += (char)('0' + d);
- } else {
- current_entry_string += (char)('a' + d - 10);
- }
- refresh();
- }
-
- void add_period() {
- point_entered = true;
- fraction_digits = 0;
- current_entry_string += ".";
- add_history_char('.');
- refresh();
- }
-
- void enter() {
- CR entry;
- add_history_string(current_entry_string);
- if (point_entered && fraction_digits > 0) {
- CR divisor = CR.valueOf(current_big_base.pow(fraction_digits));
- entry = CR.valueOf(current_entry).divide(divisor);
- } else {
- entry = CR.valueOf(current_entry);
- }
- push(entry);
- clear_current_entry();
- }
-
- final static int scroll_max = 100;
- final static int scroll_min = -100;
-
- static int prec_from_scroll_setting(int setting) {
- int result;
- if (setting >= -50 && setting <= 50) {
- return -setting;
- }
- if (setting > 50) return - (20 * (setting - 50) + 50);
- return - (20 * (setting + 50) - 50);
- }
-
- static int scroll_setting_from_prec(int prec) {
- int result;
- if (prec >= -50 && prec <= 50) {
- return -prec;
- }
- if (prec > 50) return - ((prec - 50)/20 + 50);
- return - ((prec + 50)/20 - 50);
- }
-
- // Common fixups when precision changes for any reason.
- void prec_changed(boolean set_text) {
- int scroll_val = scroll_setting_from_prec(current_prec);
- prec_scroll.setValue(scroll_val);
- if (set_text) prec_window.setText(String.valueOf(current_prec));
- enqueueKeyCommand(command_queue.refresh_command);
- }
-
- // Handle adjustment events for precision scroll bar.
- public void adjustmentValueChanged(AdjustmentEvent e) {
- int scroll_val = prec_scroll.getValue();
- current_prec = prec_from_scroll_setting(scroll_val);
- prec_changed(true);
- }
-
- // Text events for precision window
- public void textValueChanged(TextEvent e) {
- int new_prec;
- String new_text = prec_window.getText();
- if (new_text.compareTo("-") == 0) {
- // incomplete entry
- return;
- }
- try {
- new_prec = Integer.parseInt(new_text);
- } catch (NumberFormatException exc) {
- warn("Syntax error in precision");
- prec_window.setText(String.valueOf(current_prec));
- return;
- }
- if (current_prec != new_prec) {
- current_prec = new_prec;
- prec_changed(false);
- }
- }
-
-// void set_sizes() {
-// Dimension sz = this.getSize();
-// int width = sz.width;
-// int height = sz.height;
-// System.out.println("width = " + width + "height = " + height);
-// display_width = width - 50;
-// display_char_width = display_width/10;
-// prec_scroll.setSize(display_width, 20);
-// display.setSize(display_width, height/2);
-// display_char_width = display.getRows();
-// System.out.println("display_char_width = " + display_char_width);
-// }
-
- public void init() {
- // setBackground(new Color(0x6699ff));
- Font big_font = new Font("Helvetica", Font.BOLD, 18);
- Font medium_font = new Font("Helvetica", Font.PLAIN, 14);
- display_width = 450;
- display_char_width = 44;
- // Netscape TextAreas appear to be smaller than they're supposed
- // to be, at least under Irix. Thus we pad unless told otherwise.
- int extra_columns = 0;
- int extra_rows = 0;
- int rows = 10;
- if (is_applet) {
- String extra_rows_string = getParameter("extra_rows");
- String rows_string = getParameter("rows");
- String extra_columns_string = getParameter("extra_rows");
- extra_columns = 2;
- extra_rows = 1;
- try {
- if (null != extra_rows_string) {
- extra_rows = Integer.parseInt(extra_rows_string);
- }
- if (null != extra_columns_string) {
- extra_columns = Integer.parseInt(extra_columns_string);
- }
- if (null != rows_string) {
- rows = Integer.parseInt(rows_string);
- }
- } catch (NumberFormatException e) {
- System.out.println("Format error in display size parameter");
- }
- }
- display = new TextArea("", rows+extra_rows,
- display_char_width + extra_columns,
- TextArea.SCROLLBARS_VERTICAL_ONLY);
- // display.setBackground(new Color(0x99ccff));
- int font_size = 14;
- if (null == display_font_name) {
- display_font_name = getParameter("font");
- if (null == display_font_name) display_font_name = "Courier";
- }
- if (display_font_name.compareTo("Dialog") == 0) font_size = 16;
- Font display_font = new Font(display_font_name, Font.BOLD, font_size);
- FontMetrics display_metrics = this.getFontMetrics(display_font);
- if (display_metrics.charWidth(' ') != display_metrics.charWidth('9')) {
- System.out.println("Requested display font not fixed with: "
- + "Using Courier");
- font_size = 14;
- display_font = new Font("Courier", Font.BOLD, font_size);
- }
- display.setFont(display_font);
- display.setEditable(false);
- display.addKeyListener(this);
- keypad = new Panel();
- keypad.setLayout(new GridLayout(7,5));
- control_panel = new Panel();
- control_panel.setLayout(new GridLayout(7,1));
- keypanel = new Panel();
- current_prec = initial_prec;
- prec_scroll_panel = new Panel();
- prec_scroll_panel.setSize(300, 20);
- prec_scroll.setValues(current_prec, 1, -100, 100);
- prec_scroll_panel.setLayout(new GridLayout(2,1));
- prec_scroll_panel.add(prec_scroll);
- Canvas c = new Canvas();
- c.setSize(300, 2);
- prec_scroll_panel.add(c);
- // prec_scroll.setSize(display_width, 20);
- prec_scroll.addAdjustmentListener(this);
- prec_window.setText(String.valueOf(current_prec));
- prec_window.setEditable(true);
- prec_window.addTextListener(this);
- prec_scroll.setValue(scroll_setting_from_prec(current_prec));
-
- add_button = new Button("+");
- add_button.setActionCommand("+");
- add_button.addActionListener(this);
- multiply_button = new Button("*");
- multiply_button.setActionCommand("*");
- multiply_button.addActionListener(this);
- subtract_button = new Button("-");
- subtract_button.setActionCommand("-");
- subtract_button.addActionListener(this);
- divide_button = new Button("/");
- divide_button.setActionCommand("/");
- divide_button.addActionListener(this);
- power_button = new Button("x^y");
- power_button.setActionCommand("^");
- power_button.addActionListener(this);
- enter_button = new Button("enter");
- enter_button.setActionCommand("$");
- enter_button.addActionListener(this);
- negate_button = new Button("+/-");
- negate_button.setActionCommand("~");
- negate_button.addActionListener(this);
- inverse_button = new Button("1/x");
- inverse_button.setActionCommand("%");
- inverse_button.addActionListener(this);
- exp_button = new Button("exp");
- exp_button.setActionCommand("x");
- exp_button.addActionListener(this);
- sqrt_button = new Button("sqrt");
- sqrt_button.setActionCommand("r");
- sqrt_button.addActionListener(this);
- ln_button = new Button("ln");
- ln_button.setActionCommand("l");
- ln_button.addActionListener(this);
- pi_button = new Button("pi");
- pi_button.setActionCommand("p");
- pi_button.addActionListener(this);
- dot_button = new Button(".");
- dot_button.setActionCommand(".");
- dot_button.addActionListener(this);
- dot_button.setFont(big_font);
- sin_button = new Button("sin");
- sin_button.setActionCommand("s");
- sin_button.addActionListener(this);
- cos_button = new Button("cos");
- cos_button.setActionCommand("k");
- cos_button.addActionListener(this);
- tan_button = new Button("tan");
- tan_button.setActionCommand("t");
- tan_button.addActionListener(this);
- asin_button = new Button("asin");
- asin_button.setActionCommand("S");
- asin_button.addActionListener(this);
- acos_button = new Button("acos");
- acos_button.setActionCommand("K");
- acos_button.addActionListener(this);
- atan_button = new Button("atan");
- atan_button.setActionCommand("T");
- atan_button.addActionListener(this);
- help_button = new Button("HELP!");
- help_button.addActionListener(this);
- help_button.setFont(medium_font);
- stop_button = new Button("stop");
- stop_button.addActionListener(this);
- stop_button.setFont(medium_font);
-// paste_button = new Button("paste cb");
-// paste_button.addActionListener(this);
- write_button = new Button("write");
- write_button.addActionListener(this);
- write_button.setActionCommand("w");
- write_button.setFont(medium_font);
- base_box = new Checkbox("base 16");
- base_box.addItemListener(this);
- base_box.setFont(medium_font);
- degree_box = new Checkbox("degrees");
- degree_box.addItemListener(this);
- degree_box.setFont(medium_font);
- replay_button = new Button("replay");
- replay_button.addActionListener(this);
- replay_button.setFont(medium_font);
- set_prec_button = new Button("set prec.");
- set_prec_button.addActionListener(this);
- set_prec_button.setFont(medium_font);
- set_prec_button.setActionCommand(">");
- xchg_button = new Button("xchg");
- xchg_button.setActionCommand("i");
- xchg_button.addActionListener(this);
- clear_button = new Button("C/CE");
- clear_button.setActionCommand("#");
- clear_button.addActionListener(this);
- clear_all_button = new Button("C All");
- clear_all_button.setActionCommand("@");
- clear_all_button.addActionListener(this);
- store_button = new Button("store M");
- store_button.setActionCommand("=");
- store_button.addActionListener(this);
- recall_button = new Button("get M");
- recall_button.setActionCommand("g");
- recall_button.addActionListener(this);
- copy_button = new Button("copy");
- copy_button.setActionCommand("q");
- copy_button.addActionListener(this);
- history = new TextArea("", 1 + extra_columns,
- display_char_width,
- TextArea.SCROLLBARS_HORIZONTAL_ONLY);
- control_panel.add(stop_button);
- control_panel.add(help_button);
- control_panel.add(set_prec_button);
- control_panel.add(replay_button);
- control_panel.add(write_button);
- control_panel.add(base_box);
- control_panel.add(degree_box);
- history.setEditable(true);
- for (int i = 0; i <= 9; ++i) {
- String name = (new Integer(i)).toString();
- digit_button[i] = new Button(name);
- digit_button[i].setActionCommand(String.valueOf((char)('0' + i)));
- digit_button[i].addActionListener(this);
- digit_button[i].setFont(big_font);
- }
- // row 0
- keypad.add(inverse_button);
- keypad.add(sqrt_button);
- keypad.add(exp_button);
- keypad.add(ln_button);
- keypad.add(power_button);
- // row 1
- keypad.add(clear_button);
- keypad.add(sin_button);
- keypad.add(cos_button);
- keypad.add(tan_button);
- keypad.add(pi_button);
- // row 2
- keypad.add(clear_all_button);
- keypad.add(asin_button);
- keypad.add(acos_button);
- keypad.add(atan_button);
- keypad.add(divide_button);
- // row 3
- keypad.add(xchg_button);
- for (int i = 7; i <= 9; ++i) keypad.add(digit_button[i]);
- keypad.add(multiply_button);
- // row 4
- keypad.add(store_button);
- for (int i = 4; i <= 6; ++i) keypad.add(digit_button[i]);
- keypad.add(subtract_button);
- // row 5
- keypad.add(recall_button);
- for (int i = 1; i <= 3; ++i) keypad.add(digit_button[i]);
- keypad.add(add_button);
- // row 6
- keypad.add(copy_button);
- keypad.add(digit_button[0]);
- keypad.add(dot_button);
- keypad.add(negate_button);
- keypad.add(enter_button);
-
- cq = new command_queue();
- current_base = 10;
- current_big_base = big10;
- degree_mode = false;
- input_converter = output_converter = UnaryCRFunction.identityFunction;
- clear();
-
- please_stop = false;
- please_exit = false;
- worker = new Thread(this, "CRCalc worker");
- worker.setPriority(Thread.NORM_PRIORITY - 2);
- worker.start();
- ts = new time_slicer();
- ts_thread = new Thread(ts, "CRCalc time slicer");
- ts_thread.setPriority(Thread.MAX_PRIORITY);
- ts_thread.start();
-
- this.add(display);
- this.add(prec_scroll_panel);
- this.add(prec_window);
- keypanel.add(control_panel);
- keypanel.add(keypad);
- this.add(keypanel);
- this.add(history);
- }
-
- String display_font_name = null;
-
- boolean is_applet = true;
-
- // So we can also run this as an application:
- public static void main(String argv[]) {
- Frame f = new Frame("CR Calculator");
- CRCalc calc = new CRCalc();
- calc.display_font_name = "Courier";
- calc.is_applet = false;
- calc.init();
- calc.start();
- f.add("Center", calc);
- f.setSize(500, 570);
- // calc.set_sizes();
- calc.validate();
- f.setVisible(true);
- }
-
- public void destroy() {
- cq.please_exit = true;
- ts.please_exit = true;
- please_exit = true;
- ts_thread.interrupt();
- worker.interrupt();
- // The following are probably unnecessary, but ...
- keypad.remove(add_button);
- keypad.remove(multiply_button);
- keypad.remove(subtract_button);
- keypad.remove(divide_button);
- keypad.remove(power_button);
- keypad.remove(enter_button);
- keypad.remove(negate_button);
- keypad.remove(inverse_button);
- keypad.remove(sqrt_button);
- keypad.remove(exp_button);
- keypad.remove(ln_button);
- keypad.remove(pi_button);
- keypad.remove(dot_button);
- keypad.remove(sin_button);
- keypad.remove(cos_button);
- keypad.remove(tan_button);
- keypad.remove(asin_button);
- keypad.remove(acos_button);
- keypad.remove(atan_button);
- keypad.remove(clear_button);
- keypad.remove(clear_all_button);
- keypad.remove(xchg_button);
- keypad.remove(copy_button);
- keypad.remove(store_button);
- keypad.remove(recall_button);
- for (int i = 0; i <= 9; ++i) {
- keypad.remove(digit_button[i]);
- }
- control_panel.remove(help_button);
- control_panel.remove(stop_button);
- control_panel.remove(base_box);
- control_panel.remove(degree_box);
- control_panel.remove(set_prec_button);
- control_panel.remove(replay_button);
- control_panel.remove(write_button);
- remove(keypad);
- remove(display);
- remove(prec_scroll);
- remove(prec_window);
- remove(history);
- display_font_name = null;
- }
-
- Integer busy_lock= new Integer(0);
- // Used only as lock protecting busy flag.
- boolean busy = false;
-
- void set_busy() {
- synchronized(busy_lock) {
- busy = true;
- stop_button.setLabel("STOP!");
- }
- }
-
- void clear_busy() {
- synchronized(busy_lock) {
- busy = false;
- stop_button.setLabel("stop");
- }
- }
-
- volatile boolean please_stop; // Request worker thread to stop.
-
- volatile boolean please_exit; // Request helper threads to exit.
-
- // Most real actions need to be performed in a worker thread,
- // so that they can be interrupted. This is the main procedure
- // for that thread.
- public void run() {
- char command;
- for (;;) {
- if (please_exit) return;
- command = cq.get();
- try {
- if (please_exit) return;
- if (please_stop) continue;
- set_busy();
- if (Thread.interrupted()) throw new AbortedError();
- if (!executeKeyCommand(command)) {
- warn("Bad command in command queue !?");
- }
- } catch (AbortedError e) {
- warn("Aborted");
- clear_entry();
- add_history_string("<aborted>");
- enqueueKeyCommand(command_queue.refresh_command);
- } catch (ArithmeticException e) {
- warn("Illegal operand");
- clear_entry();
- add_history_string("<error>");
- enqueueKeyCommand(command_queue.refresh_command);
- } catch (OutOfMemoryError e) {
- clear_entry();
- warn("Out of Memory");
- add_history_string("<error>");
- enqueueKeyCommand(command_queue.refresh_command);
- } catch (PrecisionOverflowError e) {
- warn("Overflow in requested precision value");
- int prec = current_prec;
- if (prec < -1000 || prec > 1000) {
- current_prec = initial_prec;
- prec_changed(true);
- } else {
- clear_entry();
- add_history_string("<error>");
- enqueueKeyCommand(command_queue.refresh_command);
- }
- }
- clear_busy();
- CR.please_stop = false;
- }
- }
-
- void do_stop() {
- synchronized(busy_lock) {
- if (busy) {
- worker.interrupt();
- CR.please_stop = true;
- }
- }
- }
-
- void enqueueCommands(String commands) {
- int len = commands.length();
- for (int i = 0; i < len; ++i) {
- enqueueKeyCommand(commands.charAt(i));
- }
- }
-
-// This doesn't really seem to be useful, given the extent of clipboard
-// support in browsers and JVMs. It would be nice, but ...
-// String get_clipboard_data() {
-// try {
-// Clipboard cb = this.getToolkit().getSystemClipboard();
-// Transferable contents = cb.getContents(this);
-// String data = (String)
-// contents.getTransferData(DataFlavor.stringFlavor);
-// if (data.length() == 0) warn("No data in clipboard");
-// return data;
-// } catch (SecurityException e) {
-// warn("Applet is not allowed to retrieve clipboard");
-// } catch (UnsupportedFlavorException e) {
-// warn("Unsupported clipboard data format");
-// } catch (java.io.IOException e) {
-// warn("Error reading clipboard data");
-// }
-// return "";
-// }
-
- public void actionPerformed(ActionEvent e) {
- String command_string = e.getActionCommand();
- if (command_string.length() == 1) {
- // It's the command to execute.
- enqueueKeyCommand(command_string.charAt(0));
- } else {
- Object source = e.getSource();
- if (source == help_button) {
- msg(help_text);
- } else if (source == stop_button) {
- do_stop();
- } else if (source == replay_button) {
- String commands = history.getSelectedText();
- int len = commands.length();
- if (len == 0) {
- warn("No text selected in history buffer");
- } else {
- enqueueCommands(commands);
- }
-// } else if (source == paste_button) {
-// String commands = get_clipboard_data();
-// int len = commands.length();
-// if (len != 0) {
-// enqueueCommands(commands);
-// }
- }
- }
- }
-
- public void keyTyped(KeyEvent e) { e.consume(); }
-
- public void keyReleased(KeyEvent e) { e.consume(); }
-
- public void keyPressed(KeyEvent e) {
- char key = e.getKeyChar();
- if (enqueueKeyCommand(key)) e.consume();
- }
-
- public void itemStateChanged(ItemEvent e) {
- if (e.getItemSelectable() == base_box) {
- if (base_box.getState() && 10 == current_base) {
- enqueueKeyCommand('!');
- } else if (!base_box.getState() && 16 == current_base) {
- enqueueKeyCommand('!');
- }
- } else if (e.getItemSelectable() == degree_box) {
- if (degree_box.getState() && !degree_mode) {
- enqueueKeyCommand('\"');
- } else if (!degree_box.getState() && degree_mode) {
- enqueueKeyCommand('\"');
- }
- }
- }
-
- void wait_a_little() {
- try {
- Thread.sleep(5000);
- } catch(InterruptedException e) {}
- }
-
- final int check_prec = -500; // eval precision for arg checks.
-
- // Execute the command corresponding to a keyboard key.
- boolean executeKeyCommand(char key) {
- int signum;
- switch(key) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- add_digit(key - '0');
- break;
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- add_digit(key - 'a' + 10);
- break;
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- add_digit(key - 'A' + 10);
- break;
- case '$':
- case ' ':
- case '\r':
- case '\n':
- do_unary(UnaryCRFunction.identityFunction, '$');
- break;
- case '.':
- add_period();
- break;
- case '+':
- do_add();
- break;
- case '-':
- do_subtract();
- break;
- case '*':
- do_multiply();
- break;
- case '/':
- if (!check_binary()) break;
- if (stack[stack_ptr-1].signum(check_prec) == 0) {
- if (!ask("Probable division by 0. Proceed?")) break;
- }
- do_divide();
- break;
- case '^':
- if (!check_binary()) break;
- signum = stack[stack_ptr-2].signum(check_prec);
- if (signum < 0) {
- warn("Negative base not allowed");
- break;
- }
- if (signum == 0) {
- if (!ask("Base must be > 0, but appears to be 0. Proceed?"))
- break;
- }
- do_power();
- break;
- case '~':
- do_unary(UnaryCRFunction.negateFunction, '~');
- break;
- case '%':
- if (!check_unary()) break;
- if (stack[stack_ptr-1].signum(check_prec) == 0) {
- if (!ask("Probable division by 0. Proceed?")) break;
- }
- do_unary(UnaryCRFunction.inverseFunction, '%');
- break;
- case 'r':
- case 'R':
- if (!check_unary()) break;
- if (stack[stack_ptr-1].signum(check_prec) < 0) {
- warn("Square root of negative number");
- } else {
- do_unary(UnaryCRFunction.sqrtFunction, 'r');
- }
- break;
- case 'x':
- case 'X':
- do_unary(UnaryCRFunction.expFunction, 'x');
- break;
- case 'l':
- case 'L':
- if (!check_unary()) break;
- signum = stack[stack_ptr-1].signum(check_prec);
- if (signum < 0) {
- warn("log(negative number)");
- break;
- }
- if (signum == 0) {
- if (!ask("Probable log(0). Proceed?")) break;
- }
- do_unary(UnaryCRFunction.lnFunction, 'l');
- break;
- case 'p':
- case 'P':
- do_pi();
- break;
- case 's':
- do_unary(UnaryCRFunction.sinFunction.compose(input_converter),
- 's');
- break;
- case 'k':
- do_unary(UnaryCRFunction.cosFunction.compose(input_converter),
- 'k');
- break;
- case 't':
- if (!check_unary()) break;
- // Check for an argument that is an odd multiple of PI/2
- // Do this in stages, to make it cheaper.
- {
- CR top = stack[stack_ptr-1];
- CR half = CR.valueOf(1).shiftRight(1);
- CR pi_mul = top.divide(CR.PI).subtract(half);
- int initial_check_prec = check_prec/10;
- BigInteger pi_mul_appr = pi_mul.get_appr(initial_check_prec);
- if (pi_mul_appr.shiftRight(-initial_check_prec)
- .shiftLeft(-initial_check_prec)
- .equals(pi_mul_appr)) {
- pi_mul_appr = pi_mul.get_appr(check_prec);
- if (pi_mul_appr.shiftRight(-check_prec)
- .shiftLeft(-check_prec)
- .equals(pi_mul_appr)) {
- if (!ask("Probable diverging tan(). Proceed?")) break;
- }
- }
- }
-
- do_unary(UnaryCRFunction.tanFunction.compose(input_converter),
- 't');
- break;
- case 'S':
- do_unary(output_converter.compose(UnaryCRFunction.asinFunction),
- 'S');
- break;
- case 'K':
- do_unary(output_converter.compose(UnaryCRFunction.acosFunction),
- 'K');
- break;
- case 'T':
- do_unary(output_converter.compose(UnaryCRFunction.atanFunction),
- 'T');
- break;
- case 'w':
- case 'W': // write
- if (!check_unary()) break;
- int convert_prec = current_prec >= 0? 0 : -current_prec;
- String tos = stack[stack_ptr-1].toString(convert_prec
- + extra_prec,
- current_base);
- int len = tos.length();
- System.out.println(tos.substring(0, len-extra_prec));
- break;
- case '>': // set precision
- add_history_char('>');
- if (!check_unary()) break;
- current_prec = stack[--stack_ptr].intValue();
- prec_changed(true);
- break;
- case 'q':
- case 'Q':
- do_copy();
- break;
- case 'i':
- case 'I':
- do_exchange();
- break;
- case '=':
- do_store();
- break;
- case 'g':
- do_recall();
- break;
- case '\b':
- if (digits_entered > 0 || point_entered) {
- delete_last_char();
- refresh();
- break;
- } // else fall through and clear entry;
- case '#':
- if (digits_entered == 0) add_history_char('#');
- clear_entry();
- refresh();
- break;
- case '@':
- add_history_char('@');
- clear();
- refresh();
- break;
- case command_queue.refresh_command:
- // internal use only
- refresh();
- break;
- case '!':
- add_history_char('!');
- if (current_base == 10) {
- current_base = 16;
- current_big_base = big16;
- if (!base_box.getState()) base_box.setState(true);
- } else {
- current_base = 10;
- current_big_base = big10;
- if (base_box.getState()) base_box.setState(false);
- }
- refresh();
- break;
- case '\"':
- add_history_char('\"');
- if (degree_mode) {
- degree_mode = false;
- input_converter = UnaryCRFunction.identityFunction;
- output_converter = UnaryCRFunction.identityFunction;
- if (degree_box.getState()) degree_box.setState(false);
- } else {
- degree_mode = true;
- input_converter = from_degrees;
- output_converter = to_degrees;
- if (!degree_box.getState()) degree_box.setState(true);
- }
- refresh();
- break;
- default:
- return false;
- }
- return true;
- }
-
- // Enqueue the command corresponding to a keyboard key.
- // Return true if it is a valid command.
- boolean enqueueKeyCommand(char key) {
- switch(key) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '$':
- case ' ':
- case '\r':
- case '\n':
- case '.':
- case '+':
- case '-':
- case '*':
- case '/':
- case '^':
- case '~':
- case '%':
- case 'r':
- case 'R':
- case 'x':
- case 'X':
- case 'l':
- case 'L':
- case 'p':
- case 'P':
- case 's':
- case 'k':
- case 't':
- case 'S':
- case 'K':
- case 'T':
- case 'q':
- case 'Q':
- case 'i':
- case 'I':
- case '=':
- case 'g':
- case '#':
- case '\b':
- case '@':
- case '!':
- case '\"':
- case 'w':
- case 'W':
- case '>':
- case command_queue.refresh_command:
- cq.add(key);
- return true;
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- if (current_base == 16) {
- cq.add(key);
- return true;
- } else {
- return false;
- }
- default:
- return false;
- }
- }
-
-
- public String getAppletInfo() {
- return "SGI Calculator for demand evaluated real numbers V 0.4.\n"
- + "Author: Hans-J. Boehm\n"
- + "Copyright © 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED\n"
- + "See COPYRIGHT.txt for details.\n";
- }
-
- private String[][] param_info = {
- {"font", "font family name", "font for display window"},
- {"rows", "decimal integer", "number of rows in display"},
- {"extra_rows", "decimal integer",
- "rows of padding in display and history"},
- {"extra_columns", "decimal integer",
- "padding columns in display"},
- };
-
- public String[][] getParameterInfo() { return param_info; }
-
-}
diff --git a/src/PrecisionOverflowError.java b/src/PrecisionOverflowError.java
index 3c2da57..e294596 100644
--- a/src/PrecisionOverflowError.java
+++ b/src/PrecisionOverflowError.java
@@ -1,9 +1,9 @@
-// Copyright (c) 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED
-//
+// Copyright (c) 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED
+//
// Permission is granted free of charge to copy, modify, use and distribute
// this software provided you include the entirety of this notice in all
// copies made.
-//
+//
// THIS SOFTWARE IS PROVIDED ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
// WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT
@@ -13,7 +13,7 @@
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES
// AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS
// AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
-//
+//
// UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING,
// WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY), CONTRACT, OR
// OTHERWISE, SHALL SGI BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL,
@@ -26,7 +26,7 @@
// LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
// EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT
// EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
-//
+//
// These license terms shall be governed by and construed in accordance with
// the laws of the United States and the State of California as applied to
// agreements entered into and to be performed entirely within California
@@ -34,7 +34,7 @@
// terms shall be subject to the exclusive jurisdiction of the Federal Courts
// of the Northern District of California (or, absent subject matter
// jurisdiction in such courts, the courts of the State of California), with
-// venue lying exclusively in Santa Clara County, California.
+// venue lying exclusively in Santa Clara County, California.
package com.sgi.math;
diff --git a/src/UnaryCRFunction.java b/src/UnaryCRFunction.java
index 12dd6dd..1062918 100644
--- a/src/UnaryCRFunction.java
+++ b/src/UnaryCRFunction.java
@@ -1,9 +1,9 @@
-// Copyright (c) 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED
-//
+// Copyright (c) 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED
+//
// Permission is granted free of charge to copy, modify, use and distribute
// this software provided you include the entirety of this notice in all
// copies made.
-//
+//
// THIS SOFTWARE IS PROVIDED ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
// WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT
@@ -13,7 +13,7 @@
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES
// AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS
// AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
-//
+//
// UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING,
// WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY), CONTRACT, OR
// OTHERWISE, SHALL SGI BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL,
@@ -26,7 +26,7 @@
// LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
// EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT
// EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
-//
+//
// These license terms shall be governed by and construed in accordance with
// the laws of the United States and the State of California as applied to
// agreements entered into and to be performed entirely within California
@@ -34,7 +34,7 @@
// terms shall be subject to the exclusive jurisdiction of the Federal Courts
// of the Northern District of California (or, absent subject matter
// jurisdiction in such courts, the courts of the State of California), with
-// venue lying exclusively in Santa Clara County, California.
+// venue lying exclusively in Santa Clara County, California.
package com.sgi.math;
@@ -54,49 +54,49 @@ public abstract class UnaryCRFunction {
* The function object corresponding to the identity function.
*/
public static final UnaryCRFunction identityFunction =
- new identity_UnaryCRFunction();
+ new identity_UnaryCRFunction();
/**
* The function object corresponding to the <TT>negate</tt> method of CR.
*/
public static final UnaryCRFunction negateFunction =
- new negate_UnaryCRFunction();
+ new negate_UnaryCRFunction();
/**
* The function object corresponding to the <TT>inverse</tt> method of CR.
*/
public static final UnaryCRFunction inverseFunction =
- new inverse_UnaryCRFunction();
+ new inverse_UnaryCRFunction();
/**
* The function object corresponding to the <TT>abs</tt> method of CR.
*/
public static final UnaryCRFunction absFunction =
- new abs_UnaryCRFunction();
+ new abs_UnaryCRFunction();
/**
* The function object corresponding to the <TT>exp</tt> method of CR.
*/
public static final UnaryCRFunction expFunction =
- new exp_UnaryCRFunction();
+ new exp_UnaryCRFunction();
/**
* The function object corresponding to the <TT>cos</tt> method of CR.
*/
public static final UnaryCRFunction cosFunction =
- new cos_UnaryCRFunction();
+ new cos_UnaryCRFunction();
/**
* The function object corresponding to the <TT>sin</tt> method of CR.
*/
public static final UnaryCRFunction sinFunction =
- new sin_UnaryCRFunction();
+ new sin_UnaryCRFunction();
/**
* The function object corresponding to the tangent function.
*/
public static final UnaryCRFunction tanFunction =
- new tan_UnaryCRFunction();
+ new tan_UnaryCRFunction();
// Helper for some of the following public members.
static CR half_pi = CR.PI.divide(CR.valueOf(2));
@@ -106,7 +106,7 @@ public abstract class UnaryCRFunction {
* -PI/2 and PI/2.
*/
public static final UnaryCRFunction asinFunction =
- UnaryCRFunction.sinFunction.inverseMonotone(half_pi.negate(), half_pi);
+ UnaryCRFunction.sinFunction.inverseMonotone(half_pi.negate(), half_pi);
/**
* The function object corresponding to the inverse cosine (arccosine) function.
@@ -114,32 +114,32 @@ public abstract class UnaryCRFunction {
* 0 and PI.
*/
public static final UnaryCRFunction acosFunction =
- new acos_UnaryCRFunction();
+ new acos_UnaryCRFunction();
/**
* The function object corresponding to the inverse cosine (arctangent) function.
* The result is between -PI/2 and PI/2.
*/
public static final UnaryCRFunction atanFunction =
- new atan_UnaryCRFunction();
+ new atan_UnaryCRFunction();
/**
* The function object corresponding to the <TT>ln</tt> method of CR.
*/
public static final UnaryCRFunction lnFunction =
- new ln_UnaryCRFunction();
-
+ new ln_UnaryCRFunction();
+
/**
* The function object corresponding to the <TT>sqrt</tt> method of CR.
*/
public static final UnaryCRFunction sqrtFunction =
- new sqrt_UnaryCRFunction();
-
+ new sqrt_UnaryCRFunction();
+
/**
* Compose this function with <TT>f2</tt>.
*/
public UnaryCRFunction compose(UnaryCRFunction f2) {
- return new compose_UnaryCRFunction(this, f2);
+ return new compose_UnaryCRFunction(this, f2);
}
/**
@@ -150,7 +150,7 @@ public abstract class UnaryCRFunction {
* The original function may be either increasing or decreasing.
*/
public UnaryCRFunction inverseMonotone(CR low, CR high) {
- return new inverseMonotone_UnaryCRFunction(this, low, high);
+ return new inverseMonotone_UnaryCRFunction(this, low, high);
}
/**
@@ -161,7 +161,7 @@ public abstract class UnaryCRFunction {
* The result is defined only in the open interval.
*/
public UnaryCRFunction monotoneDerivative(CR low, CR high) {
- return new monotoneDerivative_UnaryCRFunction(this, low, high);
+ return new monotoneDerivative_UnaryCRFunction(this, low, high);
}
}
@@ -169,25 +169,25 @@ public abstract class UnaryCRFunction {
// Subclasses of UnaryCRFunction for various built-in functions.
class sin_UnaryCRFunction extends UnaryCRFunction {
public CR execute(CR x) {
- return x.sin();
+ return x.sin();
}
}
class cos_UnaryCRFunction extends UnaryCRFunction {
public CR execute(CR x) {
- return x.cos();
+ return x.cos();
}
}
class tan_UnaryCRFunction extends UnaryCRFunction {
public CR execute(CR x) {
- return x.sin().divide(x.cos());
+ return x.sin().divide(x.cos());
}
}
class acos_UnaryCRFunction extends UnaryCRFunction {
public CR execute(CR x) {
- return half_pi.subtract(asinFunction.execute(x));
+ return half_pi.subtract(asinFunction.execute(x));
}
}
@@ -198,52 +198,52 @@ class acos_UnaryCRFunction extends UnaryCRFunction {
class atan_UnaryCRFunction extends UnaryCRFunction {
CR one = CR.valueOf(1);
public CR execute(CR x) {
- CR x2 = x.multiply(x);
- CR abs_sin_atan = x2.divide(one.add(x2)).sqrt();
- CR sin_atan = x.select(abs_sin_atan.negate(), abs_sin_atan);
- return asinFunction.execute(sin_atan);
+ CR x2 = x.multiply(x);
+ CR abs_sin_atan = x2.divide(one.add(x2)).sqrt();
+ CR sin_atan = x.select(abs_sin_atan.negate(), abs_sin_atan);
+ return asinFunction.execute(sin_atan);
}
}
class exp_UnaryCRFunction extends UnaryCRFunction {
public CR execute(CR x) {
- return x.exp();
+ return x.exp();
}
}
class ln_UnaryCRFunction extends UnaryCRFunction {
public CR execute(CR x) {
- return x.ln();
+ return x.ln();
}
}
class identity_UnaryCRFunction extends UnaryCRFunction {
public CR execute(CR x) {
- return x;
+ return x;
}
}
class negate_UnaryCRFunction extends UnaryCRFunction {
public CR execute(CR x) {
- return x.negate();
+ return x.negate();
}
}
class inverse_UnaryCRFunction extends UnaryCRFunction {
public CR execute(CR x) {
- return x.inverse();
+ return x.inverse();
}
}
class abs_UnaryCRFunction extends UnaryCRFunction {
public CR execute(CR x) {
- return x.abs();
+ return x.abs();
}
}
class sqrt_UnaryCRFunction extends UnaryCRFunction {
public CR execute(CR x) {
- return x.sqrt();
+ return x.sqrt();
}
}
@@ -251,11 +251,11 @@ class compose_UnaryCRFunction extends UnaryCRFunction {
UnaryCRFunction f1;
UnaryCRFunction f2;
compose_UnaryCRFunction(UnaryCRFunction func1,
- UnaryCRFunction func2) {
- f1 = func1; f2 = func2;
+ UnaryCRFunction func2) {
+ f1 = func1; f2 = func2;
}
public CR execute(CR x) {
- return f1.execute(f2.execute(x));
+ return f1.execute(f2.execute(x));
}
}
@@ -265,297 +265,297 @@ class inverseMonotone_UnaryCRFunction extends UnaryCRFunction {
// I couldn't find a way to initialize these such that the
// compiler accepted them as final without turning them into arrays.
final UnaryCRFunction f[] = new UnaryCRFunction[1];
- // Monotone increasing.
- // If it was monotone decreasing, we
- // negate it.
+ // Monotone increasing.
+ // If it was monotone decreasing, we
+ // negate it.
final boolean f_negated[] = new boolean[1];
final CR low[] = new CR[1];
final CR high[] = new CR[1];
final CR f_low[] = new CR[1];
final CR f_high[] = new CR[1];
final int max_msd[] = new int[1];
- // Bound on msd of both f(high) and f(low)
+ // Bound on msd of both f(high) and f(low)
final int max_arg_prec[] = new int[1];
- // base**max_arg_prec is a small fraction
- // of low - high.
+ // base**max_arg_prec is a small fraction
+ // of low - high.
final int deriv_msd[] = new int[1];
- // Rough approx. of msd of first
- // derivative.
+ // Rough approx. of msd of first
+ // derivative.
inverseMonotone_UnaryCRFunction(UnaryCRFunction func, CR l, CR h) {
- low[0] = l; high[0] = h;
+ low[0] = l; high[0] = h;
CR tmp_f_low = func.execute(l);
CR tmp_f_high = func.execute(h);
- // Since func is monotone and low < high, the following test
- // converges.
- if (tmp_f_low.compareTo(tmp_f_high) > 0) {
- f[0] = UnaryCRFunction.negateFunction.compose(func);
- f_negated[0] = true;
- f_low[0] = tmp_f_low.negate();
- f_high[0] = tmp_f_high.negate();
- } else {
- f[0] = func;
- f_negated[0] = false;
- f_low[0] = tmp_f_low;
- f_high[0] = tmp_f_high;
- }
+ // Since func is monotone and low < high, the following test
+ // converges.
+ if (tmp_f_low.compareTo(tmp_f_high) > 0) {
+ f[0] = UnaryCRFunction.negateFunction.compose(func);
+ f_negated[0] = true;
+ f_low[0] = tmp_f_low.negate();
+ f_high[0] = tmp_f_high.negate();
+ } else {
+ f[0] = func;
+ f_negated[0] = false;
+ f_low[0] = tmp_f_low;
+ f_high[0] = tmp_f_high;
+ }
max_msd[0] = low[0].abs().max(high[0].abs()).msd();
- max_arg_prec[0] = high[0].subtract(low[0]).msd() - 4;
- deriv_msd[0] = f_high[0].subtract(f_low[0])
- .divide(high[0].subtract(low[0])).msd();
+ max_arg_prec[0] = high[0].subtract(low[0]).msd() - 4;
+ deriv_msd[0] = f_high[0].subtract(f_low[0])
+ .divide(high[0].subtract(low[0])).msd();
}
class inverseIncreasingCR extends CR {
- final CR arg;
- inverseIncreasingCR(CR x) {
- arg = f_negated[0]? x.negate() : x;
- }
- // Comparison with a difference of one treated as equality.
- int sloppy_compare(BigInteger x, BigInteger y) {
- BigInteger difference = x.subtract(y);
- if (difference.compareTo(big1) > 0) {
- return 1;
- }
- if (difference.compareTo(bigm1) < 0) {
- return -1;
- }
- return 0;
- }
- protected BigInteger approximate(int p) {
- final boolean trace = false; // Change to generate trace
- final int extra_arg_prec = 4;
- final UnaryCRFunction fn = f[0];
- int small_steps = 0; // Number of preceding ineffective
- // steps. If this number gets >= 2,
- // we perform a binary search step
- // to ensure forward progress.
- int digits_needed = max_msd[0] - p;
- if (digits_needed < 0) return big0;
- int working_arg_prec = p - extra_arg_prec;
- if (working_arg_prec > max_arg_prec[0]) {
- working_arg_prec = max_arg_prec[0];
- }
- int working_eval_prec = working_arg_prec + deriv_msd[0] - 20;
- // initial guess
- // We use a combination of binary search and something like
- // the secant method. This always converges linearly,
- // and should converge quadratically for well-behaved
- // functions.
- // F_l and f_h are always the approximate images of l and h.
- // At any point, arg is between f_l and f_h, or no more than
- // one outside [f_l, f_h].
- // L and h are implicitly scaled by working_arg_prec.
- // The scaled values of l and h are strictly between low and high.
- // If at_left is true, then l is logically at the left
- // end of the interval. We approximate this by setting l to
- // a point slightly inside the interval, and letting f_l
- // approximate the function value at the endpoint.
- // If at_right is true, r and f_r are set correspondingly.
- // At the endpoints of the interval, f_l and f_h may correspond
- // to the endpoints, even if l and h are slightly inside.
- // F_l and f_u are scaled by working_eval_prec.
- // Working_eval_prec may need to be adjusted depending
- // on the derivative of f.
- boolean at_left, at_right;
- BigInteger l, f_l;
- BigInteger h, f_h;
- BigInteger low_appr = low[0].get_appr(working_arg_prec)
- .add(big1);
- BigInteger high_appr = high[0].get_appr(working_arg_prec)
- .subtract(big1);
- BigInteger arg_appr = arg.get_appr(working_eval_prec);
- boolean have_good_appr = (appr_valid && min_prec < max_msd[0]);
- if (digits_needed < 30 && !have_good_appr) {
- if (trace) {
- System.out.println("Setting interval to entire domain");
- }
- h = high_appr;
- f_h = f_high[0].get_appr(working_eval_prec);
- l = low_appr;
- f_l = f_low[0].get_appr(working_eval_prec);
- // Check for clear out-of-bounds case.
- // Close cases may fail in other ways.
- if (f_h.compareTo(arg_appr.subtract(big1)) < 0
- || f_l.compareTo(arg_appr.add(big1)) > 0) {
- throw new ArithmeticException();
- }
- at_left = true;
- at_right = true;
- small_steps = 2; // Start with bin search step.
- } else {
- int rough_prec = p + digits_needed/2;
-
- if (have_good_appr &&
- (digits_needed < 30 || min_prec < p + 3*digits_needed/4)) {
- rough_prec = min_prec;
- }
- BigInteger rough_appr = get_appr(rough_prec);
- if (trace) {
- System.out.println("Setting interval based on prev. appr");
- System.out.println("prev. prec = " + rough_prec
- + " appr = " + rough_appr);
- }
- h = rough_appr.add(big1)
- .shiftLeft(rough_prec - working_arg_prec);
- l = rough_appr.subtract(big1)
- .shiftLeft(rough_prec - working_arg_prec);
- if (h.compareTo(high_appr) > 0) {
- h = high_appr;
- f_h = f_high[0].get_appr(working_eval_prec);
- at_right = true;
- } else {
- CR h_cr = CR.valueOf(h).shiftLeft(working_arg_prec);
- f_h = fn.execute(h_cr).get_appr(working_eval_prec);
- at_right = false;
- }
- if (l.compareTo(low_appr) < 0) {
- l = low_appr;
- f_l = f_low[0].get_appr(working_eval_prec);
- at_left = true;
- } else {
- CR l_cr = CR.valueOf(l).shiftLeft(working_arg_prec);
- f_l = fn.execute(l_cr).get_appr(working_eval_prec);
- at_left = false;
- }
- }
- BigInteger difference = h.subtract(l);
- for(int i = 0;; ++i) {
- if (Thread.interrupted() || please_stop)
- throw new AbortedError();
- if (trace) {
- System.out.println("***Iteration: " + i);
- System.out.println("Arg prec = " + working_arg_prec
- + " eval prec = " + working_eval_prec
- + " arg appr. = " + arg_appr);
- System.out.println("l = " + l + "; h = " + h);
- System.out.println("f(l) = " + f_l + "; f(h) = " + f_h);
- }
- if (difference.compareTo(big6) < 0) {
- // Answer is less than 1/2 ulp away from h.
- return scale(h, -extra_arg_prec);
- }
- BigInteger f_difference = f_h.subtract(f_l);
- // Narrow the interval by dividing at a cleverly
- // chosen point (guess) in the middle.
- {
- BigInteger guess;
- if (small_steps >= 2 || f_difference.signum() == 0) {
- // Do a binary search step to guarantee linear
- // convergence.
- guess = l.add(h).shiftRight(1);
- } else {
- // interpolate.
- // f_difference is nonzero here.
- BigInteger arg_difference = arg_appr.subtract(f_l);
- BigInteger t = arg_difference.multiply(difference);
- BigInteger adj = t.divide(f_difference);
- if (adj.compareTo(difference.shiftRight(2)) < 0) {
- // Very close to left side of interval;
- // move closer to center.
- // If one of the endpoints is very close to
- // the answer, this slows conversion a bit.
- // But it greatly increases the probability
- // that the answer will be in the smaller
- // subinterval.
- adj = adj.shiftLeft(1);
- } else if (adj.compareTo(difference.multiply(CR.big3)
- .shiftRight(2)) > 0){
- adj = difference.subtract(difference.subtract(adj)
- .shiftLeft(1));
- }
- if (adj.signum() <= 0)
- adj = big2;
- if (adj.compareTo(difference) >= 0)
- adj = difference.subtract(big2);
- guess = (adj.signum() <= 0? l.add(big2) : l.add(adj));
- }
- int outcome;
- BigInteger tweak = big2;
- BigInteger f_guess;
- for(boolean adj_prec = false;; adj_prec = !adj_prec) {
- CR guess_cr = CR.valueOf(guess)
- .shiftLeft(working_arg_prec);
- if (trace) {
- System.out.println("Evaluating at " + guess_cr
- + " with precision "
- + working_eval_prec);
- }
- CR f_guess_cr = fn.execute(guess_cr);
- if (trace) {
- System.out.println("fn value = " + f_guess_cr);
- }
- f_guess = f_guess_cr.get_appr(working_eval_prec);
- outcome = sloppy_compare(f_guess, arg_appr);
- if (outcome != 0) break;
- // Alternately increase evaluation precision
- // and adjust guess slightly.
- // This should be an unlikely case.
- if (adj_prec) {
- // adjust working_eval_prec to get enough
- // resolution.
- int adjustment = deriv_msd[0] > 0 ? -20 :
- deriv_msd[0] - 20;
- CR l_cr = CR.valueOf(l)
- .shiftLeft(working_arg_prec);
- CR h_cr = CR.valueOf(h)
- .shiftLeft(working_arg_prec);
- working_eval_prec += adjustment;
- if (trace) {
- System.out.println("New eval prec = "
- + working_eval_prec
- + (at_left? "(at left)" : "")
- + (at_right? "(at right)" : ""));
- }
- if (at_left) {
- f_l = f_low[0].get_appr(working_eval_prec);
- } else {
- f_l = fn.execute(l_cr)
- .get_appr(working_eval_prec);
- }
- if (at_right) {
- f_h = f_high[0].get_appr(working_eval_prec);
- } else {
- f_h = fn.execute(h_cr)
- .get_appr(working_eval_prec);
- }
- arg_appr = arg.get_appr(working_eval_prec);
- } else {
- // guess might be exactly right; tweak it
- // slightly.
- if (trace) System.out.println("tweaking guess");
- BigInteger new_guess = guess.add(tweak);
- if (new_guess.compareTo(h) >= 0) {
- guess = guess.subtract(tweak);
- } else {
- guess = new_guess;
- }
- // If we keep hitting the right answer, it's
- // important to alternate which side we move it
- // to, so that the interval shrinks rapidly.
- tweak = tweak.negate();
- }
- }
- if (outcome > 0) {
- h = guess;
- f_h = f_guess;
- at_right = false;
- } else {
- l = guess;
- f_l = f_guess;
- at_left = false;
- }
- BigInteger new_difference = h.subtract(l);
- if (new_difference.compareTo(difference
- .shiftRight(1)) >= 0) {
- ++small_steps;
- } else {
- small_steps = 0;
- }
- difference = new_difference;
- }
- }
- }
+ final CR arg;
+ inverseIncreasingCR(CR x) {
+ arg = f_negated[0]? x.negate() : x;
+ }
+ // Comparison with a difference of one treated as equality.
+ int sloppy_compare(BigInteger x, BigInteger y) {
+ BigInteger difference = x.subtract(y);
+ if (difference.compareTo(big1) > 0) {
+ return 1;
+ }
+ if (difference.compareTo(bigm1) < 0) {
+ return -1;
+ }
+ return 0;
+ }
+ protected BigInteger approximate(int p) {
+ final boolean trace = false; // Change to generate trace
+ final int extra_arg_prec = 4;
+ final UnaryCRFunction fn = f[0];
+ int small_steps = 0; // Number of preceding ineffective
+ // steps. If this number gets >= 2,
+ // we perform a binary search step
+ // to ensure forward progress.
+ int digits_needed = max_msd[0] - p;
+ if (digits_needed < 0) return big0;
+ int working_arg_prec = p - extra_arg_prec;
+ if (working_arg_prec > max_arg_prec[0]) {
+ working_arg_prec = max_arg_prec[0];
+ }
+ int working_eval_prec = working_arg_prec + deriv_msd[0] - 20;
+ // initial guess
+ // We use a combination of binary search and something like
+ // the secant method. This always converges linearly,
+ // and should converge quadratically for well-behaved
+ // functions.
+ // F_l and f_h are always the approximate images of l and h.
+ // At any point, arg is between f_l and f_h, or no more than
+ // one outside [f_l, f_h].
+ // L and h are implicitly scaled by working_arg_prec.
+ // The scaled values of l and h are strictly between low and high.
+ // If at_left is true, then l is logically at the left
+ // end of the interval. We approximate this by setting l to
+ // a point slightly inside the interval, and letting f_l
+ // approximate the function value at the endpoint.
+ // If at_right is true, r and f_r are set correspondingly.
+ // At the endpoints of the interval, f_l and f_h may correspond
+ // to the endpoints, even if l and h are slightly inside.
+ // F_l and f_u are scaled by working_eval_prec.
+ // Working_eval_prec may need to be adjusted depending
+ // on the derivative of f.
+ boolean at_left, at_right;
+ BigInteger l, f_l;
+ BigInteger h, f_h;
+ BigInteger low_appr = low[0].get_appr(working_arg_prec)
+ .add(big1);
+ BigInteger high_appr = high[0].get_appr(working_arg_prec)
+ .subtract(big1);
+ BigInteger arg_appr = arg.get_appr(working_eval_prec);
+ boolean have_good_appr = (appr_valid && min_prec < max_msd[0]);
+ if (digits_needed < 30 && !have_good_appr) {
+ if (trace) {
+ System.out.println("Setting interval to entire domain");
+ }
+ h = high_appr;
+ f_h = f_high[0].get_appr(working_eval_prec);
+ l = low_appr;
+ f_l = f_low[0].get_appr(working_eval_prec);
+ // Check for clear out-of-bounds case.
+ // Close cases may fail in other ways.
+ if (f_h.compareTo(arg_appr.subtract(big1)) < 0
+ || f_l.compareTo(arg_appr.add(big1)) > 0) {
+ throw new ArithmeticException();
+ }
+ at_left = true;
+ at_right = true;
+ small_steps = 2; // Start with bin search step.
+ } else {
+ int rough_prec = p + digits_needed/2;
+
+ if (have_good_appr &&
+ (digits_needed < 30 || min_prec < p + 3*digits_needed/4)) {
+ rough_prec = min_prec;
+ }
+ BigInteger rough_appr = get_appr(rough_prec);
+ if (trace) {
+ System.out.println("Setting interval based on prev. appr");
+ System.out.println("prev. prec = " + rough_prec
+ + " appr = " + rough_appr);
+ }
+ h = rough_appr.add(big1)
+ .shiftLeft(rough_prec - working_arg_prec);
+ l = rough_appr.subtract(big1)
+ .shiftLeft(rough_prec - working_arg_prec);
+ if (h.compareTo(high_appr) > 0) {
+ h = high_appr;
+ f_h = f_high[0].get_appr(working_eval_prec);
+ at_right = true;
+ } else {
+ CR h_cr = CR.valueOf(h).shiftLeft(working_arg_prec);
+ f_h = fn.execute(h_cr).get_appr(working_eval_prec);
+ at_right = false;
+ }
+ if (l.compareTo(low_appr) < 0) {
+ l = low_appr;
+ f_l = f_low[0].get_appr(working_eval_prec);
+ at_left = true;
+ } else {
+ CR l_cr = CR.valueOf(l).shiftLeft(working_arg_prec);
+ f_l = fn.execute(l_cr).get_appr(working_eval_prec);
+ at_left = false;
+ }
+ }
+ BigInteger difference = h.subtract(l);
+ for(int i = 0;; ++i) {
+ if (Thread.interrupted() || please_stop)
+ throw new AbortedError();
+ if (trace) {
+ System.out.println("***Iteration: " + i);
+ System.out.println("Arg prec = " + working_arg_prec
+ + " eval prec = " + working_eval_prec
+ + " arg appr. = " + arg_appr);
+ System.out.println("l = " + l + "; h = " + h);
+ System.out.println("f(l) = " + f_l + "; f(h) = " + f_h);
+ }
+ if (difference.compareTo(big6) < 0) {
+ // Answer is less than 1/2 ulp away from h.
+ return scale(h, -extra_arg_prec);
+ }
+ BigInteger f_difference = f_h.subtract(f_l);
+ // Narrow the interval by dividing at a cleverly
+ // chosen point (guess) in the middle.
+ {
+ BigInteger guess;
+ if (small_steps >= 2 || f_difference.signum() == 0) {
+ // Do a binary search step to guarantee linear
+ // convergence.
+ guess = l.add(h).shiftRight(1);
+ } else {
+ // interpolate.
+ // f_difference is nonzero here.
+ BigInteger arg_difference = arg_appr.subtract(f_l);
+ BigInteger t = arg_difference.multiply(difference);
+ BigInteger adj = t.divide(f_difference);
+ if (adj.compareTo(difference.shiftRight(2)) < 0) {
+ // Very close to left side of interval;
+ // move closer to center.
+ // If one of the endpoints is very close to
+ // the answer, this slows conversion a bit.
+ // But it greatly increases the probability
+ // that the answer will be in the smaller
+ // subinterval.
+ adj = adj.shiftLeft(1);
+ } else if (adj.compareTo(difference.multiply(CR.big3)
+ .shiftRight(2)) > 0){
+ adj = difference.subtract(difference.subtract(adj)
+ .shiftLeft(1));
+ }
+ if (adj.signum() <= 0)
+ adj = big2;
+ if (adj.compareTo(difference) >= 0)
+ adj = difference.subtract(big2);
+ guess = (adj.signum() <= 0? l.add(big2) : l.add(adj));
+ }
+ int outcome;
+ BigInteger tweak = big2;
+ BigInteger f_guess;
+ for(boolean adj_prec = false;; adj_prec = !adj_prec) {
+ CR guess_cr = CR.valueOf(guess)
+ .shiftLeft(working_arg_prec);
+ if (trace) {
+ System.out.println("Evaluating at " + guess_cr
+ + " with precision "
+ + working_eval_prec);
+ }
+ CR f_guess_cr = fn.execute(guess_cr);
+ if (trace) {
+ System.out.println("fn value = " + f_guess_cr);
+ }
+ f_guess = f_guess_cr.get_appr(working_eval_prec);
+ outcome = sloppy_compare(f_guess, arg_appr);
+ if (outcome != 0) break;
+ // Alternately increase evaluation precision
+ // and adjust guess slightly.
+ // This should be an unlikely case.
+ if (adj_prec) {
+ // adjust working_eval_prec to get enough
+ // resolution.
+ int adjustment = deriv_msd[0] > 0 ? -20 :
+ deriv_msd[0] - 20;
+ CR l_cr = CR.valueOf(l)
+ .shiftLeft(working_arg_prec);
+ CR h_cr = CR.valueOf(h)
+ .shiftLeft(working_arg_prec);
+ working_eval_prec += adjustment;
+ if (trace) {
+ System.out.println("New eval prec = "
+ + working_eval_prec
+ + (at_left? "(at left)" : "")
+ + (at_right? "(at right)" : ""));
+ }
+ if (at_left) {
+ f_l = f_low[0].get_appr(working_eval_prec);
+ } else {
+ f_l = fn.execute(l_cr)
+ .get_appr(working_eval_prec);
+ }
+ if (at_right) {
+ f_h = f_high[0].get_appr(working_eval_prec);
+ } else {
+ f_h = fn.execute(h_cr)
+ .get_appr(working_eval_prec);
+ }
+ arg_appr = arg.get_appr(working_eval_prec);
+ } else {
+ // guess might be exactly right; tweak it
+ // slightly.
+ if (trace) System.out.println("tweaking guess");
+ BigInteger new_guess = guess.add(tweak);
+ if (new_guess.compareTo(h) >= 0) {
+ guess = guess.subtract(tweak);
+ } else {
+ guess = new_guess;
+ }
+ // If we keep hitting the right answer, it's
+ // important to alternate which side we move it
+ // to, so that the interval shrinks rapidly.
+ tweak = tweak.negate();
+ }
+ }
+ if (outcome > 0) {
+ h = guess;
+ f_h = f_guess;
+ at_right = false;
+ } else {
+ l = guess;
+ f_l = f_guess;
+ at_left = false;
+ }
+ BigInteger new_difference = h.subtract(l);
+ if (new_difference.compareTo(difference
+ .shiftRight(1)) >= 0) {
+ ++small_steps;
+ } else {
+ small_steps = 0;
+ }
+ difference = new_difference;
+ }
+ }
+ }
}
public CR execute(CR x) {
- return new inverseIncreasingCR(x);
+ return new inverseIncreasingCR(x);
}
}
@@ -563,9 +563,9 @@ class monotoneDerivative_UnaryCRFunction extends UnaryCRFunction {
// The following variables are final, so that they
// can be referenced from the inner class inverseIncreasingCR.
final UnaryCRFunction f[] = new UnaryCRFunction[1];
- // Monotone increasing.
- // If it was monotone decreasing, we
- // negate it.
+ // Monotone increasing.
+ // If it was monotone decreasing, we
+ // negate it.
final CR low[] = new CR[1]; // endpoints and mispoint of interval
final CR mid[] = new CR[1];
final CR high[] = new CR[1];
@@ -574,84 +574,84 @@ class monotoneDerivative_UnaryCRFunction extends UnaryCRFunction {
final CR f_high[] = new CR[1];
final int difference_msd[] = new int[1]; // msd of interval len.
final int deriv2_msd[] = new int[1];
- // Rough approx. of msd of second
- // derivative.
- // This is increased to be an appr. bound
- // on the msd of |(f'(y)-f'(x))/(x-y)|
- // for any pair of points x and y
- // we have considered.
- // It may be better to keep a copy per
- // derivative value.
+ // Rough approx. of msd of second
+ // derivative.
+ // This is increased to be an appr. bound
+ // on the msd of |(f'(y)-f'(x))/(x-y)|
+ // for any pair of points x and y
+ // we have considered.
+ // It may be better to keep a copy per
+ // derivative value.
monotoneDerivative_UnaryCRFunction(UnaryCRFunction func, CR l, CR h) {
- f[0] = func;
- low[0] = l; high[0] = h;
- mid[0] = l.add(h).shiftRight(1);
+ f[0] = func;
+ low[0] = l; high[0] = h;
+ mid[0] = l.add(h).shiftRight(1);
f_low[0] = func.execute(l);
f_mid[0] = func.execute(mid[0]);
f_high[0] = func.execute(h);
- CR difference = h.subtract(l);
- // compute approximate msd of
- // ((f_high - f_mid) - (f_mid - f_low))/(high - low)
- // This should be a very rough appr to the second derivative.
- // We add a little slop to err on the high side, since
- // a low estimate will cause extra iterations.
- CR appr_diff2 = f_high[0].subtract(f_mid[0].shiftLeft(1)).add(f_low[0]);
- difference_msd[0] = difference.msd();
- deriv2_msd[0] = appr_diff2.msd() - difference_msd[0] + 4;
+ CR difference = h.subtract(l);
+ // compute approximate msd of
+ // ((f_high - f_mid) - (f_mid - f_low))/(high - low)
+ // This should be a very rough appr to the second derivative.
+ // We add a little slop to err on the high side, since
+ // a low estimate will cause extra iterations.
+ CR appr_diff2 = f_high[0].subtract(f_mid[0].shiftLeft(1)).add(f_low[0]);
+ difference_msd[0] = difference.msd();
+ deriv2_msd[0] = appr_diff2.msd() - difference_msd[0] + 4;
}
class monotoneDerivativeCR extends CR {
- CR arg;
- CR f_arg;
- int max_delta_msd;
- monotoneDerivativeCR(CR x) {
- arg = x;
- f_arg = f[0].execute(x);
- // The following must converge, since arg must be in the
- // open interval.
- CR left_diff = arg.subtract(low[0]);
- int max_delta_left_msd = left_diff.msd();
- CR right_diff = high[0].subtract(arg);
- int max_delta_right_msd = right_diff.msd();
- if (left_diff.signum() < 0 || right_diff.signum() < 0) {
- throw new ArithmeticException();
- }
- max_delta_msd = (max_delta_left_msd < max_delta_right_msd?
- max_delta_left_msd
- : max_delta_right_msd);
- }
- protected BigInteger approximate(int p) {
- final int extra_prec = 4;
- int log_delta = p - deriv2_msd[0];
- // Ensure that we stay within the interval.
- if (log_delta > max_delta_msd) log_delta = max_delta_msd;
- log_delta -= extra_prec;
- CR delta = one.shiftLeft(log_delta);
-
- CR left = arg.subtract(delta);
- CR right = arg.add(delta);
- CR f_left = f[0].execute(left);
- CR f_right = f[0].execute(right);
- CR left_deriv = f_arg.subtract(f_left).shiftRight(log_delta);
- CR right_deriv = f_right.subtract(f_arg).shiftRight(log_delta);
- int eval_prec = p - extra_prec;
- BigInteger appr_left_deriv = left_deriv.get_appr(eval_prec);
- BigInteger appr_right_deriv = right_deriv.get_appr(eval_prec);
- BigInteger deriv_difference =
- appr_right_deriv.subtract(appr_left_deriv).abs();
- if (deriv_difference.compareTo(big8) < 0) {
- return scale(appr_left_deriv, -extra_prec);
- } else {
- if (Thread.interrupted() || please_stop)
- throw new AbortedError();
- deriv2_msd[0] =
- eval_prec + deriv_difference.bitLength() + 4/*slop*/;
- deriv2_msd[0] -= log_delta;
- return approximate(p);
- }
+ CR arg;
+ CR f_arg;
+ int max_delta_msd;
+ monotoneDerivativeCR(CR x) {
+ arg = x;
+ f_arg = f[0].execute(x);
+ // The following must converge, since arg must be in the
+ // open interval.
+ CR left_diff = arg.subtract(low[0]);
+ int max_delta_left_msd = left_diff.msd();
+ CR right_diff = high[0].subtract(arg);
+ int max_delta_right_msd = right_diff.msd();
+ if (left_diff.signum() < 0 || right_diff.signum() < 0) {
+ throw new ArithmeticException();
+ }
+ max_delta_msd = (max_delta_left_msd < max_delta_right_msd?
+ max_delta_left_msd
+ : max_delta_right_msd);
+ }
+ protected BigInteger approximate(int p) {
+ final int extra_prec = 4;
+ int log_delta = p - deriv2_msd[0];
+ // Ensure that we stay within the interval.
+ if (log_delta > max_delta_msd) log_delta = max_delta_msd;
+ log_delta -= extra_prec;
+ CR delta = one.shiftLeft(log_delta);
+
+ CR left = arg.subtract(delta);
+ CR right = arg.add(delta);
+ CR f_left = f[0].execute(left);
+ CR f_right = f[0].execute(right);
+ CR left_deriv = f_arg.subtract(f_left).shiftRight(log_delta);
+ CR right_deriv = f_right.subtract(f_arg).shiftRight(log_delta);
+ int eval_prec = p - extra_prec;
+ BigInteger appr_left_deriv = left_deriv.get_appr(eval_prec);
+ BigInteger appr_right_deriv = right_deriv.get_appr(eval_prec);
+ BigInteger deriv_difference =
+ appr_right_deriv.subtract(appr_left_deriv).abs();
+ if (deriv_difference.compareTo(big8) < 0) {
+ return scale(appr_left_deriv, -extra_prec);
+ } else {
+ if (Thread.interrupted() || please_stop)
+ throw new AbortedError();
+ deriv2_msd[0] =
+ eval_prec + deriv_difference.bitLength() + 4/*slop*/;
+ deriv2_msd[0] -= log_delta;
+ return approximate(p);
+ }
}
}
public CR execute(CR x) {
- return new monotoneDerivativeCR(x);
+ return new monotoneDerivativeCR(x);
}
}
diff --git a/src/rpn_calc.java b/src/rpn_calc.java
deleted file mode 100644
index 8c9688b..0000000
--- a/src/rpn_calc.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (c) 2001 Hewlett-Packard Company
- *
- * Permission to use, copy, modify, distribute and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation.
- * HEWLETT-PACKARD COMPANY MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY
- * OF THIS SOFTWARE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT
- * EXPRESS OR IMPLIED WARRANTY.
- */
-
-//
-// This is a simple command-line calculator driver for the Java constructive
-// reals library. In most cases, the GUI version CRCalc.java will be
-// preferable. But this version can be built without awt support, making
-// it buildable, e.g. with early versions of gcj.
-// This driver is completely single-threaded.
-// No attempt is made to handle nonterminating computations. The user
-// will have to kill the process if he/she starts one.
-//
-// Note that this was developed at Hewlett-Packard, and
-// not part of the package originally distributed by SGI.
-//
-// Author: Hans-J. Boehm (Hans_Boehm@hp.com, boehm@acm.org)
-//
-
-import com.sgi.math.CR;
-import com.sgi.math.UnaryCRFunction;
-import java.math.BigInteger;
-import java.io.DataInputStream;
-
-class rpn_calc {
- static String help_string = "This is a basic RPN calculator.\n" +
- "Each input line consists of decimal numbers separated by\n" +
- "operators or spaces. The calculator prints the top of stack\n" +
- "(if any) after processing each line. A line consisting of\n" +
- "just an \"a\" will print the entire stack.\n\n" +
- "Operators:\n" +
- "+ (add); - (subtract); * (multiply); / (divide); ^ (exponentiate)\n" +
- "e (exp); l (ln); s (sin); S (asin); c (cos); C (acos);\n" +
- "t (tan); T (atan); r (sqrt) ~ (negate)\n" +
- "q (copy top); i (interchange top two); [n]> more prec. " +
- "[n]< less prec.\n" +
- "p (enter PI); h (print help); d (delete entry); x (exit)\n" +
- "stack overflow and nontermination (e.g. division by zero) are NOT\n" +
- "handled correctly in this version.\n";
-
- static BigInteger input = BigInteger.valueOf(0);
- static int fraction_digits = 0;
- static boolean point_entered = false;
- static boolean entry_pending = false;
- static void process_digit(int d) {
- input = input.multiply(BigInteger.valueOf(10));
- input = input.add(BigInteger.valueOf(d));
- if (point_entered) fraction_digits++;
- entry_pending = true;
- }
- static void process_point() {
- point_entered = true;
- }
- static void clear_entry() {
- input = BigInteger.valueOf(0);
- fraction_digits = 0;
- point_entered = false;
- entry_pending = false;
- }
- static CR input_value() {
- CR divisor = CR.valueOf(BigInteger.valueOf(10).pow(fraction_digits));
- return CR.valueOf(input).divide(divisor);
- }
- static void enter() {
- if (entry_pending) push(input_value());
- clear_entry();
- }
- static CR memory = CR.valueOf(0);
- static DataInputStream in = new DataInputStream(System.in);
- static CR stack[] = new CR[1000];
- static int stack_ptr = 0; /* Number of valid entries. */
- static void push(CR x) { stack[stack_ptr] = x; stack_ptr++; }
- static CR top() {
- return stack[stack_ptr-1];
- }
- static CR second() {
- return stack[stack_ptr-2];
- }
- static boolean require(int n) {
- if (stack_ptr < n) {
- System.out.println("Stack underflow");
- return false;
- } else {
- return true;
- }
- }
- static void doUnary(UnaryCRFunction f) {
- enter();
- if (require(1)) {
- stack[stack_ptr-1] = f.execute(top());
- }
- }
-
- static char read_char() {
- try {
- return (char)in.readByte();
- } catch(java.io.IOException e) {
- return 'q';
- }
- }
-
- static int ndigits = 2;
-
- public static void main(String argv[]) {
- char c;
-
- for(;;) {
- c = read_char();
- if (Character.isDigit(c)) {
- process_digit(Character.digit(c, 10));
- } else if (c == '.') {
- process_point();
- } else {
- if (entry_pending && c != '<' && c != '>') enter();
- switch(c) {
- case '\n':
- if (0 != stack_ptr)
- System.out.println(top().toString(ndigits));
- break;
- case ' ':
- break;
- case '+':
- if (require(2)) {
- stack[stack_ptr-2] = second().add(top());
- -- stack_ptr;
- }
- break;
- case '-':
- if (require(2)) {
- stack[stack_ptr-2] = second().subtract(top());
- -- stack_ptr;
- }
- break;
- case '*':
- if (require(2)) {
- stack[stack_ptr-2] = second().multiply(top());
- -- stack_ptr;
- }
- break;
- case '/':
- if (require(2)) {
- stack[stack_ptr-2] = second().divide(top());
- -- stack_ptr;
- }
- break;
- case '^':
- if (require(2)) {
- CR base = stack[stack_ptr-2];
- CR exponent = stack[stack_ptr-1];
- CR result = base.ln().multiply(exponent).exp();
- stack[stack_ptr-2] = result;
- -- stack_ptr;
- }
- break;
- case '~':
- doUnary(UnaryCRFunction.negateFunction);
- break;
- case 'e':
- case 'E':
- doUnary(UnaryCRFunction.expFunction);
- break;
- case 'l':
- case 'L':
- doUnary(UnaryCRFunction.lnFunction);
- break;
- case 'r':
- case 'R':
- doUnary(UnaryCRFunction.sqrtFunction);
- break;
- case 't':
- doUnary(UnaryCRFunction.tanFunction);
- break;
- case 'T':
- doUnary(UnaryCRFunction.atanFunction);
- break;
- case 'c':
- doUnary(UnaryCRFunction.cosFunction);
- break;
- case 'C':
- doUnary(UnaryCRFunction.acosFunction);
- break;
- case 's':
- doUnary(UnaryCRFunction.sinFunction);
- break;
- case 'S':
- doUnary(UnaryCRFunction.asinFunction);
- break;
- case 'p':
- case 'P':
- push(CR.PI);
- break;
- case '=':
- if (require(1)) {
- memory = top();
- System.out.print("\nSaving: ");
- }
- break;
- case 'g':
- push(memory);
- break;
- case '>':
- if (entry_pending) {
- ndigits += input.intValue();
- clear_entry();
- } else {
- ndigits += 10;
- }
- break;
- case '<':
- if (entry_pending) {
- ndigits -= input.intValue();
- clear_entry();
- } else {
- ndigits -= 10;
- }
- if (ndigits < 0) ndigits = 0;
- break;
- case 'a':
- case 'A':
- for (int i = 0; i < stack_ptr - 1; ++i) {
- System.out.println(stack[i].toString(ndigits));
- }
- break;
- case 'd':
- case '\b':
- if (require(1))
- --stack_ptr;
- break;
- case 'q':
- case 'Q':
- if (require(1))
- push(top());
- break;
- case 'i':
- case 'I':
- if (require(2)) {
- CR tmp = top();
- stack[stack_ptr-1] = second();
- stack[stack_ptr-2] = tmp;
- }
- case 'h':
- case 'H':
- System.out.print(help_string);
- break;
- case 'x':
- case 'X':
- return;
- } /* switch */
- }
- }
- }
-}
-
diff --git a/tests/TestCR.java b/tests/TestCR.java
index 36ba789..6781ee2 100644
--- a/tests/TestCR.java
+++ b/tests/TestCR.java
@@ -1,9 +1,9 @@
-// Copyright (c) 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED
-//
+// Copyright (c) 1999, Silicon Graphics, Inc. -- ALL RIGHTS RESERVED
+//
// Permission is granted free of charge to copy, modify, use and distribute
// this software provided you include the entirety of this notice in all
// copies made.
-//
+//
// THIS SOFTWARE IS PROVIDED ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
// WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT
@@ -13,7 +13,7 @@
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES
// AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS
// AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
-//
+//
// UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING,
// WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY), CONTRACT, OR
// OTHERWISE, SHALL SGI BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL,
@@ -26,7 +26,7 @@
// LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
// EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT
// EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
-//
+//
// These license terms shall be governed by and construed in accordance with
// the laws of the United States and the State of California as applied to
// agreements entered into and to be performed entirely within California
@@ -34,7 +34,7 @@
// terms shall be subject to the exclusive jurisdiction of the Federal Courts
// of the Northern District of California (or, absent subject matter
// jurisdiction in such courts, the courts of the State of California), with
-// venue lying exclusively in Santa Clara County, California.
+// venue lying exclusively in Santa Clara County, California.
// Superficial sanity test for the constructive reals package.
@@ -45,54 +45,54 @@ import java.math.BigInteger;
public class TestCR {
static void check(boolean x, String s) {
- if (!x) System.out.println(s);
+ if (!x) System.out.println(s);
}
static void check_eq(CR x, CR y, String s) {
- if (x.compareTo(y, -50) != 0) System.out.println(s);
+ if (x.compareTo(y, -50) != 0) System.out.println(s);
}
static void check_appr_eq(double x, double y, String s) {
- if (Math.abs(x - y) > 0.000001) System.out.println(s);
+ if (Math.abs(x - y) > 0.000001) System.out.println(s);
}
public static void main(String argv[]) {
- CR zero = CR.valueOf(0);
- CR one = CR.valueOf(1);
- CR two = CR.valueOf(2);
- check(one.signum() == 1, "signum(1) failed");
- check(one.negate().signum() == -1, "signum(-1) failed");
- check(zero.signum(-100) == 0, "signum(0) failed");
- check(one.compareTo(two, -10) == -1, "comparison failed");
- check(two.toString(4).compareTo("2.0000") == 0, "toString failed");
- check_eq(one.shiftLeft(1),two, "shiftLeft failed");
- check_eq(two.shiftRight(1),one, "shiftRight failed");
- check_eq(one.add(one),two, "add failed 1");
- check_eq(one.max(two),two, "max failed");
- check_eq(one.min(two),one, "min failed");
- check_eq(one.abs(),one, "abs failed 1");
- check_eq(one.negate().abs(),one, "abs failed 2");
- CR three = two.add(one);
- CR four = two.add(two);
- check_eq(CR.valueOf(4), four, "2 + 2 failed");
- check_eq(CR.valueOf(3), three, "2 + 1 failed");
- check_eq(one.negate().add(two), one, "negate failed");
- check(one.negate().signum() == -1, "signum(-1) failed");
- check_eq(two.multiply(two), four, "multiply failed");
- check_eq(one.divide(four).shiftLeft(4), four, "divide failed 1");
- check_eq(two.divide(one.negate()), two.negate(), "divide(neg) failed");
- CR thirteen = CR.valueOf(13);
- check_eq(one.divide(thirteen).multiply(thirteen), one,
- "divide failed 2");
- check(thirteen.floatValue() == 13.0, "floatValue failed");
- check(thirteen.intValue() == 13, "intValue failed");
- check(thirteen.longValue() == 13, "longValue failed");
- check(thirteen.doubleValue() == 13.0, "doubleValue failed");
- check_eq(zero.exp(), one, "exp(0) failed");
- CR e = one.exp();
- check(e.toString(20).substring(0,17)
- .compareTo("2.718281828459045") == 0,
- "exp(1) failed");
- check_eq(e.ln(), one, "ln(e) failed");
- CR half_pi = CR.PI.divide(two);
- CR half = one.divide(two);
+ CR zero = CR.valueOf(0);
+ CR one = CR.valueOf(1);
+ CR two = CR.valueOf(2);
+ check(one.signum() == 1, "signum(1) failed");
+ check(one.negate().signum() == -1, "signum(-1) failed");
+ check(zero.signum(-100) == 0, "signum(0) failed");
+ check(one.compareTo(two, -10) == -1, "comparison failed");
+ check(two.toString(4).compareTo("2.0000") == 0, "toString failed");
+ check_eq(one.shiftLeft(1),two, "shiftLeft failed");
+ check_eq(two.shiftRight(1),one, "shiftRight failed");
+ check_eq(one.add(one),two, "add failed 1");
+ check_eq(one.max(two),two, "max failed");
+ check_eq(one.min(two),one, "min failed");
+ check_eq(one.abs(),one, "abs failed 1");
+ check_eq(one.negate().abs(),one, "abs failed 2");
+ CR three = two.add(one);
+ CR four = two.add(two);
+ check_eq(CR.valueOf(4), four, "2 + 2 failed");
+ check_eq(CR.valueOf(3), three, "2 + 1 failed");
+ check_eq(one.negate().add(two), one, "negate failed");
+ check(one.negate().signum() == -1, "signum(-1) failed");
+ check_eq(two.multiply(two), four, "multiply failed");
+ check_eq(one.divide(four).shiftLeft(4), four, "divide failed 1");
+ check_eq(two.divide(one.negate()), two.negate(), "divide(neg) failed");
+ CR thirteen = CR.valueOf(13);
+ check_eq(one.divide(thirteen).multiply(thirteen), one,
+ "divide failed 2");
+ check(thirteen.floatValue() == 13.0, "floatValue failed");
+ check(thirteen.intValue() == 13, "intValue failed");
+ check(thirteen.longValue() == 13, "longValue failed");
+ check(thirteen.doubleValue() == 13.0, "doubleValue failed");
+ check_eq(zero.exp(), one, "exp(0) failed");
+ CR e = one.exp();
+ check(e.toString(20).substring(0,17)
+ .compareTo("2.718281828459045") == 0,
+ "exp(1) failed");
+ check_eq(e.ln(), one, "ln(e) failed");
+ CR half_pi = CR.PI.divide(two);
+ CR half = one.divide(two);
BigInteger million = BigInteger.valueOf(1000*1000);
BigInteger thousand = BigInteger.valueOf(1000);
CR huge = CR.valueOf(million.multiply(million).multiply(thousand));
@@ -100,43 +100,43 @@ public class TestCR {
UnaryCRFunction acos = UnaryCRFunction.acosFunction;
UnaryCRFunction atan = UnaryCRFunction.atanFunction;
UnaryCRFunction tan = UnaryCRFunction.tanFunction;
- check_eq(half_pi.sin(), one, "sin(pi/2) failed");
- check_eq(asin.execute(one),half_pi, "asin(1) failed");
- check_eq(asin.execute(one.negate()),
- half_pi.negate(), "asin(-1) failed");
- check_eq(asin.execute(zero), zero, "asin(0) failed");
- check_eq(asin.execute(half.sin()), half, "asin(sin(0.5)) failed");
+ check_eq(half_pi.sin(), one, "sin(pi/2) failed");
+ check_eq(asin.execute(one),half_pi, "asin(1) failed");
+ check_eq(asin.execute(one.negate()),
+ half_pi.negate(), "asin(-1) failed");
+ check_eq(asin.execute(zero), zero, "asin(0) failed");
+ check_eq(asin.execute(half.sin()), half, "asin(sin(0.5)) failed");
UnaryCRFunction cosine = UnaryCRFunction.sinFunction
- .monotoneDerivative(zero, CR.PI);
- check_eq(cosine.execute(one), one.cos(), "monotoneDerivative failed");
- check_eq(cosine.execute(three), three.cos(),
- "monotoneDerivative failed 2");
- check_eq(asin.execute(one.sin()), one, "asin(sin(1) failed");
- check_eq(acos.execute(one.cos()), one, "acos(cos(1) failed");
- check_eq(atan.execute(tan.execute(one)), one, "atan(tan(1) failed");
- check_eq(atan.execute(tan.execute(one.negate())), one.negate(),
- "atan(tan(-1) failed");
+ .monotoneDerivative(zero, CR.PI);
+ check_eq(cosine.execute(one), one.cos(), "monotoneDerivative failed");
+ check_eq(cosine.execute(three), three.cos(),
+ "monotoneDerivative failed 2");
+ check_eq(asin.execute(one.sin()), one, "asin(sin(1) failed");
+ check_eq(acos.execute(one.cos()), one, "acos(cos(1) failed");
+ check_eq(atan.execute(tan.execute(one)), one, "atan(tan(1) failed");
+ check_eq(atan.execute(tan.execute(one.negate())), one.negate(),
+ "atan(tan(-1) failed");
check_eq(tan.execute(atan.execute(huge)), huge,
"tan(atan(10**15)) failed");
- CR sqrt13 = thirteen.sqrt();
- check_eq(sqrt13.multiply(sqrt13), thirteen, "sqrt(13)*sqrt(13) failed");
- CR tmp = CR.PI.add(CR.valueOf(-123).exp());
- CR tmp2 = tmp.subtract(CR.PI);
- check(tmp2.ln().intValue() == -123, "intValue(...) failed");
- check(tmp2.ln().longValue() == -123, "longValue(...) failed");
- check(tmp2.ln().floatValue() == -123.0, "floatValue(...) failed");
- check(tmp2.ln().doubleValue() == -123.0, "doubleValue(...) failed");
+ CR sqrt13 = thirteen.sqrt();
+ check_eq(sqrt13.multiply(sqrt13), thirteen, "sqrt(13)*sqrt(13) failed");
+ CR tmp = CR.PI.add(CR.valueOf(-123).exp());
+ CR tmp2 = tmp.subtract(CR.PI);
+ check(tmp2.ln().intValue() == -123, "intValue(...) failed");
+ check(tmp2.ln().longValue() == -123, "longValue(...) failed");
+ check(tmp2.ln().floatValue() == -123.0, "floatValue(...) failed");
+ check(tmp2.ln().doubleValue() == -123.0, "doubleValue(...) failed");
for (double n = -10.0; n < 10.0; n += 2.0) {
- check_appr_eq(Math.sin(n), CR.valueOf(n).sin().doubleValue(),
- "sin failed at " + n);
- check_appr_eq(Math.cos(n), CR.valueOf(n).cos().doubleValue(),
- "cos failed at " + n);
- check_appr_eq(Math.exp(n), CR.valueOf(n).exp().doubleValue(),
- "exp failed at " + n);
- if (n > 0.0) {
- check_appr_eq(Math.exp(n), CR.valueOf(n).exp().doubleValue(),
- "exp failed at " + n);
- }
- }
+ check_appr_eq(Math.sin(n), CR.valueOf(n).sin().doubleValue(),
+ "sin failed at " + n);
+ check_appr_eq(Math.cos(n), CR.valueOf(n).cos().doubleValue(),
+ "cos failed at " + n);
+ check_appr_eq(Math.exp(n), CR.valueOf(n).exp().doubleValue(),
+ "exp failed at " + n);
+ if (n > 0.0) {
+ check_appr_eq(Math.exp(n), CR.valueOf(n).exp().doubleValue(),
+ "exp failed at " + n);
+ }
+ }
}
}