GP-0 Added ability to ignore specific pcode test failures. Corrected

BigInteger to BigFloat conversion used by INT2FLOAT emulation op.
This commit is contained in:
ghidra1 2023-03-08 21:32:26 +00:00
parent a3ca5a67e1
commit f56e922d43
9 changed files with 284 additions and 105 deletions

View file

@ -18,6 +18,7 @@ package ghidra.test.processors.support;
import java.awt.Color;
import java.io.*;
import java.util.*;
import java.util.function.Predicate;
import org.jdom.Document;
import org.jdom.Element;
@ -44,6 +45,8 @@ public class PCodeTestCombinedTestResults {
private File xmlFile;
private File htmlFile;
private Map<String, Set<String>> ignoredJunitTestNames = new HashMap<>();
private Map<String, PCodeTestResults> combinedResults = new HashMap<>();
PCodeTestCombinedTestResults(File reportsDir, boolean readExisting) throws IOException {
@ -57,12 +60,31 @@ public class PCodeTestCombinedTestResults {
public PCodeTestResults getTestResults(String jUnitName, boolean create) {
PCodeTestResults testResults = combinedResults.get(jUnitName);
if (testResults == null && create) {
testResults = new PCodeTestResults(jUnitName);
testResults = new PCodeTestResults(jUnitName, new IgnoreTestPredicate(jUnitName));
combinedResults.put(jUnitName, testResults);
}
return testResults;
}
private class IgnoreTestPredicate implements Predicate<String> {
private String jUnitName;
IgnoreTestPredicate(String jUnitName) {
this.jUnitName = jUnitName;
}
@Override
public boolean test(String testName) {
Set<String> ignoredTestNames = ignoredJunitTestNames.get(jUnitName);
if (ignoredTestNames != null) {
return ignoredTestNames.contains(testName);
}
return false;
}
}
private void restoreFromXml() throws IOException {
FileInputStream istream = new FileInputStream(xmlFile);
@ -80,8 +102,10 @@ public class PCodeTestCombinedTestResults {
@SuppressWarnings("unchecked")
List<Element> elementList = root.getChildren(PCodeTestResults.TAG_NAME);
for (Element element : elementList) {
PCodeTestResults testResults = new PCodeTestResults(element);
combinedResults.put(testResults.getJUnitName(), testResults);
String jUnitName = PCodeTestResults.getJunitName(element);
PCodeTestResults testResults =
new PCodeTestResults(element, new IgnoreTestPredicate(jUnitName));
combinedResults.put(jUnitName, testResults);
}
}
catch (org.jdom.JDOMException je) {
@ -93,6 +117,14 @@ public class PCodeTestCombinedTestResults {
}
public void addIgnoredTests(String junitName, String... testNames) {
Set<String> ignoredTestSet =
ignoredJunitTestNames.computeIfAbsent(junitName, n -> new HashSet<>());
for (String testName : testNames) {
ignoredTestSet.add(testName);
}
}
void saveToXml() throws IOException {
File dir = xmlFile.getParentFile();
@ -226,7 +258,9 @@ public class PCodeTestCombinedTestResults {
return;
}
int count =
computeCharCount(testResults.passCount) + computeCharCount(testResults.failCount) +
computeCharCount(testResults.passCount) +
computeCharCount(testResults.ignoredCount) +
computeCharCount(testResults.failCount) +
computeCharCount(testResults.callOtherCount) + 2;
charCount = Math.max(count, charCount);
}
@ -433,6 +467,8 @@ public class PCodeTestCombinedTestResults {
getSummaryHighlightColorClass(testResults) + "\">");
writeResultCount(w, testResults.summaryPassCount, Palette.GREEN);
w.print("/");
writeResultCount(w, testResults.summaryIgnoreCount, Palette.GRAY);
w.print("/");
writeResultCount(w, testResults.summaryFailCount, Palette.RED);
w.print("/");
writeResultCount(w, testResults.summaryCallOtherCount, Palette.ORANGE);
@ -485,9 +521,10 @@ public class PCodeTestCombinedTestResults {
for (NamedTestColumn namedTestColumn : namedTestColumns) {
String testName = namedTestColumn.getTestName();
int pass = testResults.getPassResult(groupName, testName);
int ignored = testResults.getIgnoredResult(groupName, testName);
int fail = testResults.getFailResult(groupName, testName);
int callother = testResults.getCallOtherResult(groupName, testName);
int total = pass + fail + callother;
int total = pass + ignored + fail + callother;
int totalAsserts = testResults.getTotalAsserts(groupName, testName);
boolean severeFailure = testResults.hadSevereFailure(groupName, testName);
@ -515,6 +552,8 @@ public class PCodeTestCombinedTestResults {
else {
writeResultCount(w, pass, Palette.GREEN);
w.print("/");
writeResultCount(w, ignored, Palette.GRAY);
w.print("/");
writeResultCount(w, fail, Palette.RED);
w.print("/");
writeResultCount(w, callother, Palette.ORANGE);

View file

@ -48,6 +48,10 @@ public class PCodeTestControlBlock extends PCodeTestAbstractControlBlock {
private List<PCodeTestGroup> testGroups; // test group data
// accumulators for tests pass/fail results which have been designated as ignored
private int ignoredPassed = 0;
private int ignoredFailed = 0;
// TestInfo data read from program memory
private Address onPassFunctionAddress;
private Address onErrorFunctionAddress;
@ -319,6 +323,40 @@ public class PCodeTestControlBlock extends PCodeTestAbstractControlBlock {
emuWrite(emuTestRunner.getEmulatorHelper(), addr, SIZEOF_U4, value);
}
void resultIgnored(String testGroupName, String testName, boolean passed) {
if (passed) {
++ignoredPassed;
}
else {
++ignoredFailed;
}
testResults.addIgnoredResult(testGroupName, testName);
}
/**
* Get the number of passed tests which should be ignored
* @return number of passed tests which should be ignored
*/
int getNumberPassedIgnored() {
return ignoredPassed;
}
/**
* Get the number of failed tests which should be ignored
* @return number of failed tests which should be ignored
*/
int getNumberFailedIgnored() {
return ignoredFailed;
}
/**
* Clear ignored test result accumulators
*/
void clearNumberIgnored() {
ignoredFailed = 0;
ignoredPassed = 0;
}
/**
* Get 'numfail' field value from emulation memory state
* @param emuTestRunner emulator test runner

View file

@ -35,6 +35,10 @@ public class PCodeTestGroup implements Comparable<PCodeTestGroup> {
*/
public static final String FUNCTION_NAME_PREFIX = "main_";
public static final String IGNORED_TAG = "IGNORED";
private static final String IGNORED_FAILED_TAG = "(" + IGNORED_TAG + ")";
private static final String IGNORED_PASSED_TAG = "(Passed and " + IGNORED_TAG + ")";
public final String testGroupName;
public final Address functionEntryPtr;
// public final int testCount; // TODO: not yet fully implemented - do not use!
@ -57,31 +61,41 @@ public class PCodeTestGroup implements Comparable<PCodeTestGroup> {
return testGroupName + "@" + functionEntryPtr;
}
boolean isIgnoredTest(String testName) {
return mainTestControlBlock.getTestResults().isIgnoredTest(testName);
}
void testPassed(String testName, String errFileName, int errLineNum, Program program,
TestLogger logger) {
if (isIgnoredTest(testName)) {
mainTestControlBlock.resultIgnored(testGroupName, testName, true);
String testDetail =
getTestDetail(testName, errFileName, errLineNum, program, IGNORED_PASSED_TAG);
testFailures.add(testDetail);
logger.log(this, "WARNING! Ignored Test Passed: " + testDetail);
return;
}
mainTestControlBlock.getTestResults().addPassResult(testGroupName, testName);
}
void testFailed(String testName, String errFileName, int errLineNum, boolean callOtherFailure,
Program program, TestLogger logger) {
if (callOtherFailure) {
String ignoreTag = "";
if (isIgnoredTest(testName)) {
mainTestControlBlock.resultIgnored(testGroupName, testName, false);
ignoreTag = IGNORED_FAILED_TAG;
}
else if (callOtherFailure) {
mainTestControlBlock.getTestResults().addCallOtherResult(testGroupName, testName);
}
else {
mainTestControlBlock.getTestResults().addFailResult(testGroupName, testName);
}
String failure = testName;
if (testName != null) {
Symbol symbol = SymbolUtilities.getLabelOrFunctionSymbol(program, testName,
err -> Msg.error(this, err));
if (symbol != null) {
failure += " @ " + symbol.getAddress().toString(true);
}
failure += " (" + errFileName + ":" + errLineNum + ")";
}
testFailures.add(failure);
String testDetail = getTestDetail(testName, errFileName, errLineNum, program, ignoreTag);
testFailures.add(testDetail);
logger.log(this,
"Test Failed: " + failure + (callOtherFailure ? " (callother error)" : ""));
"Test Failed: " + testDetail +
(callOtherFailure ? " (callother error)" : ""));
}
void severeTestFailure(String testName, String errFileName, int errLineNum, Program program,
@ -94,6 +108,20 @@ public class PCodeTestGroup implements Comparable<PCodeTestGroup> {
testFailures.clear();
}
private String getTestDetail(String testName, String errFileName, int errLineNum,
Program program, String ignoreTag) {
String testDetail = testName;
if (testName != null) {
Symbol symbol = SymbolUtilities.getLabelOrFunctionSymbol(program, testName,
err -> Msg.error(this, err));
if (symbol != null) {
testDetail += " @ " + symbol.getAddress().toString(true);
}
testDetail += " (" + errFileName + ":" + errLineNum + ") " + ignoreTag;
}
return testDetail;
}
/**
* @return list of recorded emulation test failures
*/

View file

@ -18,13 +18,15 @@ package ghidra.test.processors.support;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Predicate;
import org.jdom.Attribute;
import org.jdom.Element;
public class PCodeTestResults {
private String jUnitName;
private final String jUnitName;
private final Predicate<String> ignoreTestPredicate;
boolean summaryHasIngestErrors;
boolean summaryHasRelocationErrors;
@ -32,6 +34,7 @@ public class PCodeTestResults {
int summaryTotalAsserts;
int summaryPassCount;
int summaryIgnoreCount;
int summaryFailCount;
int summaryCallOtherCount;
int summarySevereFailures;
@ -41,17 +44,91 @@ public class PCodeTestResults {
// map keys formed with "<groupName>.<testName>" string
private Map<String, TestResults> results = new HashMap<>();
PCodeTestResults(String jUnitName) {
private static String XML_VERSION = "1";
public static String TAG_NAME = "PCodeTestResults";
PCodeTestResults(String jUnitName, Predicate<String> ignoreTestPredicate) {
this.jUnitName = jUnitName;
this.ignoreTestPredicate = ignoreTestPredicate;
time = System.currentTimeMillis();
}
public PCodeTestResults(Element root, Predicate<String> ignoreTestPredicate) {
if (!TAG_NAME.equals(root.getName())) {
throw new IllegalArgumentException("Unsupported root element: " + root.getName());
}
String ver = root.getAttributeValue("VERSION");
if (!XML_VERSION.equals(ver)) {
throw new IllegalArgumentException(
"Unsupported XML format version " + ver + ", required format is " + XML_VERSION);
}
jUnitName = getJunitName(root);
this.ignoreTestPredicate = ignoreTestPredicate;
time = 0;
String timeStr = root.getAttributeValue("TIME");
if (timeStr != null) {
try {
time = Long.parseLong(timeStr);
}
catch (NumberFormatException e) {
// ignore
}
}
summaryHasIngestErrors = getAttributeValue(root, "INGEST_ERR", false);
summaryHasRelocationErrors = getAttributeValue(root, "RELOC_ERR", false);
summaryHasDisassemblyErrors = getAttributeValue(root, "DIS_ERR", false);
@SuppressWarnings("unchecked")
List<Element> elementList = root.getChildren("TestResults");
for (Element element : elementList) {
String testName = element.getAttributeValue("NAME");
if (testName == null) {
throw new IllegalArgumentException("Invalid TestResults element in XML");
}
TestResults testResults = new TestResults();
testResults.totalAsserts = getAttributeValue(element, "TOTAL_ASSERTS", 0);
testResults.passCount = getAttributeValue(element, "PASS", 0);
testResults.ignoredCount = getAttributeValue(element, "IGNORE", 0);
testResults.failCount = getAttributeValue(element, "FAIL", 0);
testResults.callOtherCount = getAttributeValue(element, "CALLOTHER", 0);
testResults.severeFailure = getAttributeValue(element, "SEVERE_FAILURE", false);
summaryTotalAsserts += testResults.totalAsserts;
summaryPassCount += testResults.passCount;
summaryIgnoreCount += testResults.ignoredCount;
summaryFailCount += testResults.failCount;
summaryCallOtherCount += testResults.callOtherCount;
if (testResults.severeFailure) {
++summarySevereFailures;
}
results.put(testName, testResults);
}
}
static String getJunitName(Element root) {
return root.getAttributeValue("JUNIT");
}
public String getJUnitName() {
return jUnitName;
}
private static DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm");
public boolean isIgnoredTest(String testName) {
if (ignoreTestPredicate != null) {
return ignoreTestPredicate.test(testName);
}
return false;
}
public String getTime() {
if (time == 0) {
return null;
@ -131,6 +208,21 @@ public class PCodeTestResults {
return 0;
}
void addIgnoredResult(String groupName, String testName) {
String groupTestName = getGroupTestName(groupName, testName);
getTestResults(groupTestName, true).ignoredCount++;
summaryIgnoreCount++;
}
public int getIgnoredResult(String groupName, String testName) {
String groupTestName = getGroupTestName(groupName, testName);
TestResults testResults = getTestResults(groupTestName, false);
if (testResults != null) {
return testResults.ignoredCount;
}
return 0;
}
void addFailResult(String groupName, String testName) {
String groupTestName = getGroupTestName(groupName, testName);
getTestResults(groupTestName, true).failCount++;
@ -183,71 +275,13 @@ public class PCodeTestResults {
summaryHasDisassemblyErrors = false;
summaryTotalAsserts = 0;
summaryPassCount = 0;
summaryIgnoreCount = 0;
summaryFailCount = 0;
summaryCallOtherCount = 0;
summarySevereFailures = 0;
time = System.currentTimeMillis();
}
private static String XML_VERSION = "1";
public static String TAG_NAME = "PCodeTestResults";
public PCodeTestResults(Element root) {
if (!TAG_NAME.equals(root.getName())) {
throw new IllegalArgumentException("Unsupported root element: " + root.getName());
}
String ver = root.getAttributeValue("VERSION");
if (!XML_VERSION.equals(ver)) {
throw new IllegalArgumentException(
"Unsupported XML format version " + ver + ", required format is " + XML_VERSION);
}
jUnitName = root.getAttributeValue("JUNIT");
time = 0;
String timeStr = root.getAttributeValue("TIME");
if (timeStr != null) {
try {
time = Long.parseLong(timeStr);
}
catch (NumberFormatException e) {
// ignore
}
}
summaryHasIngestErrors = getAttributeValue(root, "INGEST_ERR", false);
summaryHasRelocationErrors = getAttributeValue(root, "RELOC_ERR", false);
summaryHasDisassemblyErrors = getAttributeValue(root, "DIS_ERR", false);
@SuppressWarnings("unchecked")
List<Element> elementList = root.getChildren("TestResults");
for (Element element : elementList) {
String testName = element.getAttributeValue("NAME");
if (testName == null) {
throw new IllegalArgumentException("Invalid TestResults element in XML");
}
TestResults testResults = new TestResults();
testResults.totalAsserts = getAttributeValue(element, "TOTAL_ASSERTS", 0);
testResults.passCount = getAttributeValue(element, "PASS", 0);
testResults.failCount = getAttributeValue(element, "FAIL", 0);
testResults.callOtherCount = getAttributeValue(element, "CALLOTHER", 0);
testResults.severeFailure = getAttributeValue(element, "SEVERE_FAILURE", false);
summaryTotalAsserts += testResults.totalAsserts;
summaryPassCount += testResults.passCount;
summaryFailCount += testResults.failCount;
summaryCallOtherCount += testResults.callOtherCount;
if (testResults.severeFailure) {
++summarySevereFailures;
}
results.put(testName, testResults);
}
}
int getAttributeValue(Element element, String attrName, int defaultValue) {
String val = element.getAttributeValue(attrName);
if (val == null) {
@ -305,6 +339,8 @@ public class PCodeTestResults {
element.setAttribute(
new Attribute("TOTAL_ASSERTS", Integer.toString(testResults.totalAsserts)));
element.setAttribute(new Attribute("PASS", Integer.toString(testResults.passCount)));
element.setAttribute(
new Attribute("IGNORE", Integer.toString(testResults.ignoredCount)));
element.setAttribute(new Attribute("FAIL", Integer.toString(testResults.failCount)));
element.setAttribute(
new Attribute("CALLOTHER", Integer.toString(testResults.callOtherCount)));
@ -319,6 +355,7 @@ public class PCodeTestResults {
static class TestResults {
int totalAsserts;
int passCount;
int ignoredCount;
int failCount;
int callOtherCount;
@ -326,9 +363,10 @@ public class PCodeTestResults {
@Override
public String toString() {
// TODO Auto-generated method stub
return "{" + passCount + "/" + failCount + "/" + callOtherCount + "(" + totalAsserts +
return "{" + passCount + "/" + ignoredCount + "/" + failCount + "/" + callOtherCount +
"(" + totalAsserts +
")}";
}
}
}

View file

@ -18,7 +18,8 @@ package ghidra.test.processors.support;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.math.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -1180,6 +1181,7 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
// Initialize pass/fail counts at runtime to detect severe failure
testGroup.mainTestControlBlock.setNumberPassed(testRunner, Integer.MIN_VALUE);
testGroup.mainTestControlBlock.setNumberFailed(testRunner, Integer.MIN_VALUE);
testGroup.mainTestControlBlock.clearNumberIgnored();
boolean done;
if (traceDisabled) {
@ -1190,6 +1192,8 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
}
int pass = testGroup.mainTestControlBlock.getNumberPassed(testRunner);
int ignoredPassed = testGroup.mainTestControlBlock.getNumberPassedIgnored();
int ignoredFailed = testGroup.mainTestControlBlock.getNumberFailedIgnored();
int callOtherErrors = testRunner.getCallOtherErrors();
int fail = testGroup.mainTestControlBlock.getNumberFailed(testRunner);
@ -1199,21 +1203,31 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
pass + " fail " + fail);
}
pass -= ignoredPassed;
pass -= callOtherErrors;
fail -= ignoredFailed;
String passFailText = "Passed: " + pass + " Failed: " + fail;
String passFailText = "Passed: " + pass + " Ignored: " +
(ignoredFailed + ignoredPassed) + " Failed: " + fail;
if (callOtherErrors != 0) {
passFailText += " Passed(w/CALLOTHER): " + callOtherErrors;
}
passFailText += " Expected Assertions: " + totalExpectedAsserts;
log(testGroup, passFailText);
boolean hasFailures = false;
List<String> testFailures = testGroup.getTestFailures();
if (!testFailures.isEmpty()) {
log(testGroup, "TEST FAILURES:");
if (!traceDisabled) {
log(testGroup, "TEST FAILURE SUMMARY:");
}
for (String testFailure : testFailures) {
if (!traceDisabled) {
log(testGroup, " >>> " + testFailure);
}
// failure is any entry not marked as ignored
hasFailures |= (testFailure.indexOf(PCodeTestGroup.IGNORED_TAG) < 0);
}
}
if (!done) {
@ -1235,12 +1249,12 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
}
failTest(testRunner, msg.toString());
}
int ranCnt = pass + fail + callOtherErrors;
int ranCnt = pass + fail + callOtherErrors + ignoredFailed + ignoredPassed;
if ((totalExpectedAsserts != 0) && (totalExpectedAsserts != ranCnt)) {
failTest(testRunner,
"ERROR Unexpected number of assertions ( " + passFailText + " )");
}
if (fail != 0 || callOtherErrors != 0 || testFailures.size() != 0) {
if (fail != 0 || callOtherErrors != 0 || hasFailures) {
failTest(testRunner,
"ERROR One or more group tests failed ( " + passFailText + " )");
}
@ -1424,6 +1438,17 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
return maxAddr;
}
/**
* Add specified test names to the set of tests which should be ignored due to know issues
* or limitations. The tests will still be executed, if present, however they will
* not be included in pass/fail counts. They will appear in log as "(IGNORED)" test
* result.
* @param testNames one or more test names to be ignored
*/
protected void addIgnoredTests(String... testNames) {
combinedResults.addIgnoredTests(getClass().getSimpleName(), testNames);
}
//
// Protected helper methods which may be overriden
//

View file

@ -136,7 +136,8 @@
<DIV ID="topLeftTable" STYLE="position: absolute; top: 0; left: 0;">
<TABLE ID="headerTable1" BORDER=1 CELLSPACING=0 CELLPADDING=0 style="height: 100; cursor: pointer;" onclick="toggleHeaderHeight()" onmouseover="mouseOverHeader()" onmouseout="mouseOutHeader()">
<TR>
<TD CLASS="TestNameHead"><DIV STYLE="position:absolute; left: 8px; top: 5px; ">P-Code Test Results</DIV><DIV STYLE="position:absolute; left: 140px; bottom: 5px; "><font color="green" size="2">Pass</font>/<font color="red" size="2">Fail</font>/<font color="orange" size="2">CallOther</font></DIV></TD>
<TD CLASS="TestNameHead"><DIV STYLE="position:absolute; left: 8px; top: 5px; ">P-Code Test Results</DIV><DIV STYLE="position:absolute; left: 140px; bottom: 5px; ">
<font color="green" size="2">Pass</font>/<font color="gray" size="2">Ignore</font>/<font color="red" size="2">Fail</font>/<font color="orange" size="2">CallOther</font></DIV></TD>
<TD CLASS="DateTimeHead" ALIGN="center" VALIGN="bottom"><DIV CLASS="r90">DATE/TIME</DIV></TD>
<TD CLASS="ResultSummaryHead" ALIGN="center" VALIGN="bottom"><DIV CLASS="r90">SUMMARY</DIV></TD>
</TR>

View file

@ -518,6 +518,9 @@ public class EmulatorHelper implements MemoryFaultHandler, EmulatorConfiguration
if (t instanceof CancelledException) {
throw (CancelledException) t;
}
Msg.error(this,
"Emulation failure at " + emulator.getExecuteAddress() + ": " + program.getName(),
t);
}
}

View file

@ -60,8 +60,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
* @param scale value's scale (signed value with the biased range of expbits)
* @throws IllegalArgumentException if invalid unscaled and scale values are specified based upon the fracbits and expbits values.
*/
BigFloat(int fracbits, int expbits, FloatKind kind, int sign, BigInteger unscaled,
int scale) {
BigFloat(int fracbits, int expbits, FloatKind kind, int sign, BigInteger unscaled, int scale) {
this.fracbits = fracbits;
this.expbits = expbits;
this.kind = kind;
@ -151,21 +150,6 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
return true;
}
/**
* Return the BigFloat with the given number of bits representing the given BigInteger.
*
* @param fracbits number of fractional bits
* @param expbits number of bits in the exponent
* @param i an integer
* @return a BigFloat representing i
*/
public static BigFloat valueOf(int fracbits, int expbits, BigInteger i) {
BigFloat f = new BigFloat(fracbits, expbits, FloatKind.FINITE, i.signum() >= 0 ? +1 : -1,
i.abs(), fracbits);
f.scaleUpTo(fracbits + 1);
return f;
}
/**
* Return the BigFloat with the given number of bits representing zero.
*

View file

@ -897,7 +897,7 @@ public strictfp class FloatFormat {
else {
a = Utils.convertToUnsignedValue(a, sizein);
}
return getEncoding(BigFloat.valueOf(frac_size, exp_size, a));
return getEncoding(valueOf(a));
}
public long opFloat2Float(long a, FloatFormat outformat) { // convert between floating
@ -968,4 +968,27 @@ public strictfp class FloatFormat {
return getEncoding(fa);
}
public BigFloat valueOf(BigInteger value) {
BigInteger unscaled = value;
int sign = 1;
if (unscaled.signum() < 0) {
sign = -1;
unscaled = unscaled.negate();
}
int ulen = unscaled.bitLength();
int shift = frac_size + 1 - ulen;
unscaled = unscaled.shiftLeft(shift);
int scale = frac_size - shift;
if (scale > bias) {
return BigFloat.infinity(frac_size, exp_size, sign);
}
return new BigFloat(frac_size, exp_size, FloatKind.FINITE, sign, unscaled, scale);
}
}