mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
eda9127c26
36 changed files with 3492 additions and 1126 deletions
|
@ -42,7 +42,7 @@ public class ConvertToDoubleAction extends AbstractConvertAction {
|
||||||
try {
|
try {
|
||||||
FloatFormat format =
|
FloatFormat format =
|
||||||
FloatFormatFactory.getFloatFormat(dataOrganization.getDoubleSize());
|
FloatFormatFactory.getFloatFormat(dataOrganization.getDoubleSize());
|
||||||
return format.getHostFloat(s.getBigInteger());
|
return format.round(format.getHostFloat(s.getBigInteger()));
|
||||||
}
|
}
|
||||||
catch (UnsupportedFloatFormatException e) {
|
catch (UnsupportedFloatFormatException e) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class ConvertToFloatAction extends AbstractConvertAction {
|
||||||
DataOrganization dataOrganization = program.getDataTypeManager().getDataOrganization();
|
DataOrganization dataOrganization = program.getDataTypeManager().getDataOrganization();
|
||||||
try {
|
try {
|
||||||
FloatFormat format = FloatFormatFactory.getFloatFormat(dataOrganization.getFloatSize());
|
FloatFormat format = FloatFormatFactory.getFloatFormat(dataOrganization.getFloatSize());
|
||||||
return format.getHostFloat(s.getBigInteger());
|
return format.round(format.getHostFloat(s.getBigInteger()));
|
||||||
}
|
}
|
||||||
catch (UnsupportedFloatFormatException e) {
|
catch (UnsupportedFloatFormatException e) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -192,8 +192,9 @@ public class FunctionEditorModel {
|
||||||
private void notifyDataChanged(boolean functionDataChanged) {
|
private void notifyDataChanged(boolean functionDataChanged) {
|
||||||
this.modelChanged |= functionDataChanged;
|
this.modelChanged |= functionDataChanged;
|
||||||
validate();
|
validate();
|
||||||
|
if (listener != null) {
|
||||||
SwingUtilities.invokeLater(() -> listener.dataChanged());
|
SwingUtilities.invokeLater(() -> listener.dataChanged());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void notifyParsingModeChanged() {
|
// private void notifyParsingModeChanged() {
|
||||||
|
@ -580,7 +581,9 @@ public class FunctionEditorModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addParameter() {
|
public void addParameter() {
|
||||||
listener.tableRowsChanged();
|
if (listener != null) {
|
||||||
|
listener.tableRowsChanged();
|
||||||
|
}
|
||||||
ParamInfo param = new ParamInfo(this, null, DataType.DEFAULT,
|
ParamInfo param = new ParamInfo(this, null, DataType.DEFAULT,
|
||||||
VariableStorage.UNASSIGNED_STORAGE, parameters.size());
|
VariableStorage.UNASSIGNED_STORAGE, parameters.size());
|
||||||
parameters.add(param);
|
parameters.add(param);
|
||||||
|
@ -697,7 +700,9 @@ public class FunctionEditorModel {
|
||||||
if (!canRemoveParameters()) {
|
if (!canRemoveParameters()) {
|
||||||
throw new AssertException("Attempted to remove parameters when not allowed.");
|
throw new AssertException("Attempted to remove parameters when not allowed.");
|
||||||
}
|
}
|
||||||
listener.tableRowsChanged();
|
if (listener != null) {
|
||||||
|
listener.tableRowsChanged();
|
||||||
|
}
|
||||||
Arrays.sort(selectedFunctionRows);
|
Arrays.sort(selectedFunctionRows);
|
||||||
for (int i = selectedFunctionRows.length - 1; i >= 0; i--) {
|
for (int i = selectedFunctionRows.length - 1; i >= 0; i--) {
|
||||||
int index = selectedFunctionRows[i];
|
int index = selectedFunctionRows[i];
|
||||||
|
@ -719,7 +724,9 @@ public class FunctionEditorModel {
|
||||||
if (!canMoveParameterUp()) {
|
if (!canMoveParameterUp()) {
|
||||||
throw new AssertException("Attempted to move parameters up when not allowed.");
|
throw new AssertException("Attempted to move parameters up when not allowed.");
|
||||||
}
|
}
|
||||||
listener.tableRowsChanged();
|
if (listener != null) {
|
||||||
|
listener.tableRowsChanged();
|
||||||
|
}
|
||||||
int paramIndex = selectedFunctionRows[0] - 1; // first row is return value
|
int paramIndex = selectedFunctionRows[0] - 1; // first row is return value
|
||||||
ParamInfo param = parameters.remove(paramIndex);
|
ParamInfo param = parameters.remove(paramIndex);
|
||||||
parameters.add(paramIndex - 1, param);
|
parameters.add(paramIndex - 1, param);
|
||||||
|
@ -733,7 +740,9 @@ public class FunctionEditorModel {
|
||||||
if (!canMoveParameterDown()) {
|
if (!canMoveParameterDown()) {
|
||||||
throw new AssertException("Attempted to move parameters down when not allowed.");
|
throw new AssertException("Attempted to move parameters down when not allowed.");
|
||||||
}
|
}
|
||||||
listener.tableRowsChanged();
|
if (listener != null) {
|
||||||
|
listener.tableRowsChanged();
|
||||||
|
}
|
||||||
int paramIndex = selectedFunctionRows[0] - 1;
|
int paramIndex = selectedFunctionRows[0] - 1;
|
||||||
ParamInfo param = parameters.remove(paramIndex);
|
ParamInfo param = parameters.remove(paramIndex);
|
||||||
parameters.add(paramIndex + 1, param);
|
parameters.add(paramIndex + 1, param);
|
||||||
|
@ -973,8 +982,7 @@ public class FunctionEditorModel {
|
||||||
if (!paramsOrReturnModified) {
|
if (!paramsOrReturnModified) {
|
||||||
|
|
||||||
// change param names without impacting signature source
|
// change param names without impacting signature source
|
||||||
for (int i = 0; i < parameters.size(); i++) {
|
for (ParamInfo paramInfo : parameters) {
|
||||||
ParamInfo paramInfo = parameters.get(i);
|
|
||||||
if (!paramInfo.isAutoParameter() && paramInfo.isNameModified()) {
|
if (!paramInfo.isAutoParameter() && paramInfo.isNameModified()) {
|
||||||
Parameter param = paramInfo.getOriginalParameter();
|
Parameter param = paramInfo.getOriginalParameter();
|
||||||
if (param != null) {
|
if (param != null) {
|
||||||
|
@ -991,8 +999,7 @@ public class FunctionEditorModel {
|
||||||
|
|
||||||
if (paramsOrReturnModified) {
|
if (paramsOrReturnModified) {
|
||||||
List<Parameter> params = new ArrayList<>();
|
List<Parameter> params = new ArrayList<>();
|
||||||
for (int i = 0; i < parameters.size(); i++) {
|
for (ParamInfo paramInfo : parameters) {
|
||||||
ParamInfo paramInfo = parameters.get(i);
|
|
||||||
if (paramInfo.isAutoParameter()) {
|
if (paramInfo.isAutoParameter()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,7 @@ package ghidra.test.processors.support;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.math.BigDecimal;
|
import java.math.*;
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
@ -255,8 +254,10 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
try {
|
try {
|
||||||
// By default, create test output within a directory at the same level as the
|
// By default, create test output within a directory at the same level as the
|
||||||
// development repositories
|
// development repositories
|
||||||
outputRoot =
|
outputRoot = Application.getApplicationRootDirectory()
|
||||||
Application.getApplicationRootDirectory().getParentFile().getParentFile().getCanonicalPath();
|
.getParentFile()
|
||||||
|
.getParentFile()
|
||||||
|
.getCanonicalPath();
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
@ -761,15 +762,17 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
|
|
||||||
private static class FloatFormatter extends DumpFormatter {
|
private static class FloatFormatter extends DumpFormatter {
|
||||||
private final FloatFormat ff;
|
private final FloatFormat ff;
|
||||||
|
private final int maxWidth;
|
||||||
|
|
||||||
FloatFormatter(int elementSize, boolean bigEndian) {
|
FloatFormatter(int elementSize, boolean bigEndian) {
|
||||||
super(elementSize, bigEndian);
|
super(elementSize, bigEndian);
|
||||||
ff = FloatFormatFactory.getFloatFormat(elementSize);
|
ff = FloatFormatFactory.getFloatFormat(elementSize);
|
||||||
|
maxWidth = ff.round(ff.maxValue).negate().toString().length();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
int getMaxWidth() {
|
int getMaxWidth() {
|
||||||
return ff.maxValue.negate().toString().length();
|
return maxWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -779,7 +782,7 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
false)
|
false)
|
||||||
: LittleEndianDataConverter.INSTANCE.getBigInteger(bytes, index, elementSize,
|
: LittleEndianDataConverter.INSTANCE.getBigInteger(bytes, index, elementSize,
|
||||||
false);
|
false);
|
||||||
BigDecimal val = ff.getHostFloat(encoding);
|
BigDecimal val = ff.round(ff.getHostFloat(encoding));
|
||||||
return val.toString();
|
return val.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -873,7 +876,8 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
String floatStr = "";
|
String floatStr = "";
|
||||||
if (reg != null && floatRegSet.contains(reg)) {
|
if (reg != null && floatRegSet.contains(reg)) {
|
||||||
FloatFormat floatFormat = FloatFormatFactory.getFloatFormat(size);
|
FloatFormat floatFormat = FloatFormatFactory.getFloatFormat(size);
|
||||||
BigDecimal hostFloat = floatFormat.getHostFloat(new BigInteger(1, values));
|
BigDecimal hostFloat =
|
||||||
|
floatFormat.round(floatFormat.getHostFloat(new BigInteger(1, values)));
|
||||||
floatStr = " (" + hostFloat.toString() + ")";
|
floatStr = " (" + hostFloat.toString() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1640,8 +1644,8 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
if (tReg != null && (offset & 1) == 1) {
|
if (tReg != null && (offset & 1) == 1) {
|
||||||
RegisterValue thumbMode = new RegisterValue(tReg, BigInteger.ONE);
|
RegisterValue thumbMode = new RegisterValue(tReg, BigInteger.ONE);
|
||||||
try {
|
try {
|
||||||
program.getProgramContext().setRegisterValue(functionAddr, functionAddr,
|
program.getProgramContext()
|
||||||
thumbMode);
|
.setRegisterValue(functionAddr, functionAddr, thumbMode);
|
||||||
}
|
}
|
||||||
catch (ContextChangeException e) {
|
catch (ContextChangeException e) {
|
||||||
throw new AssertException(e);
|
throw new AssertException(e);
|
||||||
|
@ -1654,8 +1658,8 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
if (isaModeReg != null && (offset & 1) == 1) {
|
if (isaModeReg != null && (offset & 1) == 1) {
|
||||||
RegisterValue thumbMode = new RegisterValue(isaModeReg, BigInteger.ONE);
|
RegisterValue thumbMode = new RegisterValue(isaModeReg, BigInteger.ONE);
|
||||||
try {
|
try {
|
||||||
program.getProgramContext().setRegisterValue(functionAddr, functionAddr,
|
program.getProgramContext()
|
||||||
thumbMode);
|
.setRegisterValue(functionAddr, functionAddr, thumbMode);
|
||||||
}
|
}
|
||||||
catch (ContextChangeException e) {
|
catch (ContextChangeException e) {
|
||||||
throw new AssertException(e);
|
throw new AssertException(e);
|
||||||
|
@ -1879,8 +1883,8 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
GZF_CACHEDIR_NAME + "/" + fileReferencePath + GZF_FILE_EXT; //
|
GZF_CACHEDIR_NAME + "/" + fileReferencePath + GZF_FILE_EXT; //
|
||||||
if (absoluteGzfFilePath.exists()) {
|
if (absoluteGzfFilePath.exists()) {
|
||||||
program = getGzfProgram(outputDir, gzfCachePath);
|
program = getGzfProgram(outputDir, gzfCachePath);
|
||||||
if (program != null && !MD5Utilities.getMD5Hash(testFile.file).equals(
|
if (program != null && !MD5Utilities.getMD5Hash(testFile.file)
|
||||||
program.getExecutableMD5())) {
|
.equals(program.getExecutableMD5())) {
|
||||||
// remove obsolete GZF cache file
|
// remove obsolete GZF cache file
|
||||||
env.release(program);
|
env.release(program);
|
||||||
program = null;
|
program = null;
|
||||||
|
@ -1904,8 +1908,8 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
env.getGhidraProject().importProgram(testFile.file, loaderClass);
|
env.getGhidraProject().importProgram(testFile.file, loaderClass);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
program = env.getGhidraProject().importProgram(testFile.file, language,
|
program = env.getGhidraProject()
|
||||||
compilerSpec);
|
.importProgram(testFile.file, language, compilerSpec);
|
||||||
}
|
}
|
||||||
program.addConsumer(this);
|
program.addConsumer(this);
|
||||||
env.getGhidraProject().close(program);
|
env.getGhidraProject().close(program);
|
||||||
|
@ -1925,8 +1929,9 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
txId = program.startTransaction("Analyze");
|
txId = program.startTransaction("Analyze");
|
||||||
|
|
||||||
if (!program.getLanguageID().equals(language.getLanguageID()) ||
|
if (!program.getLanguageID().equals(language.getLanguageID()) ||
|
||||||
!program.getCompilerSpec().getCompilerSpecID().equals(
|
!program.getCompilerSpec()
|
||||||
compilerSpec.getCompilerSpecID())) {
|
.getCompilerSpecID()
|
||||||
|
.equals(compilerSpec.getCompilerSpecID())) {
|
||||||
throw new IOException((usingCachedGZF ? "Cached " : "") +
|
throw new IOException((usingCachedGZF ? "Cached " : "") +
|
||||||
"Program has incorrect language/compiler spec (" + program.getLanguageID() +
|
"Program has incorrect language/compiler spec (" + program.getLanguageID() +
|
||||||
"/" + program.getCompilerSpec().getCompilerSpecID() + "): " +
|
"/" + program.getCompilerSpec().getCompilerSpecID() + "): " +
|
||||||
|
@ -2090,8 +2095,8 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
nameAndAddr = StringUtilities.pad(nameAndAddr, ' ', -paddedLen);
|
nameAndAddr = StringUtilities.pad(nameAndAddr, ' ', -paddedLen);
|
||||||
testFileDigest.append(nameAndAddr);
|
testFileDigest.append(nameAndAddr);
|
||||||
testFileDigest.append(" (GroupInfo @ ");
|
testFileDigest.append(" (GroupInfo @ ");
|
||||||
testFileDigest.append(
|
testFileDigest
|
||||||
testGroup.controlBlock.getInfoStructureAddress().toString(true));
|
.append(testGroup.controlBlock.getInfoStructureAddress().toString(true));
|
||||||
testFileDigest.append(")");
|
testFileDigest.append(")");
|
||||||
if (duplicateTests.contains(testGroup.testGroupName)) {
|
if (duplicateTests.contains(testGroup.testGroupName)) {
|
||||||
testFileDigest.append(" *DUPLICATE*");
|
testFileDigest.append(" *DUPLICATE*");
|
||||||
|
|
|
@ -7,9 +7,11 @@ decomp_dbg
|
||||||
decomp_opt
|
decomp_opt
|
||||||
ghidra_dbg
|
ghidra_dbg
|
||||||
ghidra_opt
|
ghidra_opt
|
||||||
|
ghidra_test_dbg
|
||||||
sleigh_dbg
|
sleigh_dbg
|
||||||
com_dbg
|
com_dbg
|
||||||
com_opt
|
com_opt
|
||||||
|
test_dbg
|
||||||
ghi_dbg
|
ghi_dbg
|
||||||
ghi_opt
|
ghi_opt
|
||||||
sla_dbg
|
sla_dbg
|
||||||
|
|
|
@ -91,11 +91,11 @@ GHIDRA= ghidra_arch inject_ghidra ghidra_translate loadimage_ghidra \
|
||||||
# Additional files specific to the sleigh compiler
|
# Additional files specific to the sleigh compiler
|
||||||
SLACOMP=slgh_compile slghparse slghscan
|
SLACOMP=slgh_compile slghparse slghscan
|
||||||
# Additional special files that should not be considered part of the library
|
# Additional special files that should not be considered part of the library
|
||||||
SPECIAL=consolemain sleighexample
|
SPECIAL=consolemain sleighexample test
|
||||||
# Any additional modules for the command line decompiler
|
# Any additional modules for the command line decompiler
|
||||||
EXTRA= $(filter-out $(CORE) $(DECCORE) $(SLEIGH) $(GHIDRA) $(SLACOMP) $(SPECIAL),$(ALL_NAMES))
|
EXTRA= $(filter-out $(CORE) $(DECCORE) $(SLEIGH) $(GHIDRA) $(SLACOMP) $(SPECIAL),$(ALL_NAMES))
|
||||||
|
|
||||||
EXECS=decomp_dbg decomp_opt ghidra_dbg ghidra_opt sleigh_dbg sleigh_opt libdecomp_dbg.a libdecomp.a
|
EXECS=decomp_dbg decomp_opt ghidra_test_dbg ghidra_dbg ghidra_opt sleigh_dbg sleigh_opt libdecomp_dbg.a libdecomp.a
|
||||||
|
|
||||||
# Possible conditional compilation flags
|
# Possible conditional compilation flags
|
||||||
# __TERMINAL__ # Turn on terminal support for console mode
|
# __TERMINAL__ # Turn on terminal support for console mode
|
||||||
|
@ -114,6 +114,9 @@ COMMANDLINE_NAMES=$(CORE) $(DECCORE) $(EXTRA) $(SLEIGH) consolemain
|
||||||
COMMANDLINE_DEBUG=-DCPUI_DEBUG -D__TERMINAL__
|
COMMANDLINE_DEBUG=-DCPUI_DEBUG -D__TERMINAL__
|
||||||
COMMANDLINE_OPT=-D__TERMINAL__
|
COMMANDLINE_OPT=-D__TERMINAL__
|
||||||
|
|
||||||
|
TEST_NAMES=$(CORE) $(DECCORE) $(SLEIGH) test
|
||||||
|
TEST_DEBUG=-D__TERMINAL__ -g -O0
|
||||||
|
|
||||||
GHIDRA_NAMES=$(CORE) $(DECCORE) $(GHIDRA)
|
GHIDRA_NAMES=$(CORE) $(DECCORE) $(GHIDRA)
|
||||||
GHIDRA_NAMES_DBG=$(GHIDRA_NAMES) callgraph ifacedecomp ifaceterm interface
|
GHIDRA_NAMES_DBG=$(GHIDRA_NAMES) callgraph ifacedecomp ifaceterm interface
|
||||||
GHIDRA_DEBUG=-DCPUI_DEBUG
|
GHIDRA_DEBUG=-DCPUI_DEBUG
|
||||||
|
@ -133,6 +136,7 @@ LIBDECOMP_NAMES=$(CORE) $(DECCORE) $(EXTRA) $(SLEIGH)
|
||||||
# object file macros
|
# object file macros
|
||||||
COMMANDLINE_DBG_OBJS=$(COMMANDLINE_NAMES:%=com_dbg/%.o)
|
COMMANDLINE_DBG_OBJS=$(COMMANDLINE_NAMES:%=com_dbg/%.o)
|
||||||
COMMANDLINE_OPT_OBJS=$(COMMANDLINE_NAMES:%=com_opt/%.o)
|
COMMANDLINE_OPT_OBJS=$(COMMANDLINE_NAMES:%=com_opt/%.o)
|
||||||
|
TEST_DEBUG_OBJS=$(TEST_NAMES:%=test_dbg/%.o)
|
||||||
GHIDRA_DBG_OBJS=$(GHIDRA_NAMES_DBG:%=ghi_dbg/%.o)
|
GHIDRA_DBG_OBJS=$(GHIDRA_NAMES_DBG:%=ghi_dbg/%.o)
|
||||||
GHIDRA_OPT_OBJS=$(GHIDRA_NAMES:%=ghi_opt/%.o)
|
GHIDRA_OPT_OBJS=$(GHIDRA_NAMES:%=ghi_opt/%.o)
|
||||||
SLEIGH_DBG_OBJS=$(SLEIGH_NAMES:%=sla_dbg/%.o)
|
SLEIGH_DBG_OBJS=$(SLEIGH_NAMES:%=sla_dbg/%.o)
|
||||||
|
@ -183,6 +187,9 @@ endif
|
||||||
ifeq ($(MAKECMDGOALS),decomp_opt)
|
ifeq ($(MAKECMDGOALS),decomp_opt)
|
||||||
DEPNAMES=com_opt/depend
|
DEPNAMES=com_opt/depend
|
||||||
endif
|
endif
|
||||||
|
ifneq (,$(filter $(MAKECMDGOALS),ghidra_test_dbg test))
|
||||||
|
DEPNAMES=test_dbg/depend
|
||||||
|
endif
|
||||||
ifeq ($(MAKECMDGOALS),reallyclean)
|
ifeq ($(MAKECMDGOALS),reallyclean)
|
||||||
DEPNAMES=
|
DEPNAMES=
|
||||||
endif
|
endif
|
||||||
|
@ -206,6 +213,8 @@ com_dbg/%.o: %.cc
|
||||||
$(CXX) $(ARCH_TYPE) -c $(DBG_CXXFLAGS) $(ADDITIONAL_FLAGS) $(COMMANDLINE_DEBUG) $< -o $@
|
$(CXX) $(ARCH_TYPE) -c $(DBG_CXXFLAGS) $(ADDITIONAL_FLAGS) $(COMMANDLINE_DEBUG) $< -o $@
|
||||||
com_opt/%.o: %.cc
|
com_opt/%.o: %.cc
|
||||||
$(CXX) $(ARCH_TYPE) -c $(OPT_CXXFLAGS) $(ADDITIONAL_FLAGS) $(COMMANDLINE_OPT) $< -o $@
|
$(CXX) $(ARCH_TYPE) -c $(OPT_CXXFLAGS) $(ADDITIONAL_FLAGS) $(COMMANDLINE_OPT) $< -o $@
|
||||||
|
test_dbg/%.o: %.cc
|
||||||
|
$(CXX) $(ARCH_TYPE) -c $(OPT_CXXFLAGS) $(ADDITIONAL_FLAGS) $(TEST_DEBUG) $< -o $@
|
||||||
ghi_dbg/%.o: %.cc
|
ghi_dbg/%.o: %.cc
|
||||||
$(CXX) $(ARCH_TYPE) -c $(DBG_CXXFLAGS) $(ADDITIONAL_FLAGS) $(GHIDRA_DEBUG) $< -o $@
|
$(CXX) $(ARCH_TYPE) -c $(DBG_CXXFLAGS) $(ADDITIONAL_FLAGS) $(GHIDRA_DEBUG) $< -o $@
|
||||||
ghi_opt/%.o: %.cc
|
ghi_opt/%.o: %.cc
|
||||||
|
@ -238,6 +247,12 @@ decomp_dbg: $(COMMANDLINE_DBG_OBJS)
|
||||||
decomp_opt: $(COMMANDLINE_OPT_OBJS)
|
decomp_opt: $(COMMANDLINE_OPT_OBJS)
|
||||||
$(CXX) $(OPT_CXXFLAGS) $(ARCH_TYPE) -o decomp_opt $(COMMANDLINE_OPT_OBJS) $(BFDLIB) $(LNK)
|
$(CXX) $(OPT_CXXFLAGS) $(ARCH_TYPE) -o decomp_opt $(COMMANDLINE_OPT_OBJS) $(BFDLIB) $(LNK)
|
||||||
|
|
||||||
|
ghidra_test_dbg: $(TEST_DEBUG_OBJS)
|
||||||
|
$(CXX) $(OPT_CXXFLAGS) $(ARCH_TYPE) -o ghidra_test_dbg $(TEST_DEBUG_OBJS) $(BFDLIB) $(LNK)
|
||||||
|
|
||||||
|
test: ghidra_test_dbg
|
||||||
|
./ghidra_test_dbg
|
||||||
|
|
||||||
ghidra_dbg: $(GHIDRA_DBG_OBJS)
|
ghidra_dbg: $(GHIDRA_DBG_OBJS)
|
||||||
$(CXX) $(DBG_CXXFLAGS) $(ADDITIONAL_FLAGS) $(MAKE_STATIC) $(ARCH_TYPE) -o ghidra_dbg $(GHIDRA_DBG_OBJS) $(LNK)
|
$(CXX) $(DBG_CXXFLAGS) $(ADDITIONAL_FLAGS) $(MAKE_STATIC) $(ARCH_TYPE) -o ghidra_dbg $(GHIDRA_DBG_OBJS) $(LNK)
|
||||||
|
|
||||||
|
@ -324,6 +339,13 @@ com_opt/depend: $(COMMANDLINE_NAMES:%=%.cc)
|
||||||
sed 's,\(.*\)\.o[ :]*,com_opt/\1.o $@ : ,g' < $@.$$$$ > $@; \
|
sed 's,\(.*\)\.o[ :]*,com_opt/\1.o $@ : ,g' < $@.$$$$ > $@; \
|
||||||
rm -f $@.$$$$
|
rm -f $@.$$$$
|
||||||
|
|
||||||
|
test_dbg/depend: $(TEST_NAMES:%=%.cc)
|
||||||
|
mkdir -p test_dbg
|
||||||
|
@set -e; rm -f $@; \
|
||||||
|
$(CXX) -MM $(TEST_DEBUG) $^ > $@.$$$$; \
|
||||||
|
sed 's,\(.*\)\.o[ :]*,test_dbg/\1.o $@ : ,g' < $@.$$$$ > $@; \
|
||||||
|
rm -f $@.$$$$
|
||||||
|
|
||||||
ghi_dbg/depend: $(GHIDRA_NAMES_DBG:%=%.cc)
|
ghi_dbg/depend: $(GHIDRA_NAMES_DBG:%=%.cc)
|
||||||
mkdir -p ghi_dbg
|
mkdir -p ghi_dbg
|
||||||
@set -e; rm -f $@; \
|
@set -e; rm -f $@; \
|
||||||
|
@ -372,7 +394,7 @@ doc:
|
||||||
doxygen Doxyfile
|
doxygen Doxyfile
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f com_dbg/*.o com_opt/*.o ghi_dbg/*.o ghi_opt/*.o sla_dbg/*.o sla_opt/*.o
|
rm -f com_dbg/*.o com_opt/*.o test_dbg/*.o ghi_dbg/*.o ghi_opt/*.o sla_dbg/*.o sla_opt/*.o
|
||||||
rm -f *.gcov com_dbg/*.gcno com_dbg/*.gcda
|
rm -f *.gcov com_dbg/*.gcno com_dbg/*.gcda
|
||||||
|
|
||||||
resetgcov:
|
resetgcov:
|
||||||
|
@ -380,6 +402,6 @@ resetgcov:
|
||||||
|
|
||||||
reallyclean: clean
|
reallyclean: clean
|
||||||
rm -rf coreext_*.cc coreext_*.hh ghidraext_*.cc ghidraext_*.hh consoleext_*.cc consoleext_*.hh
|
rm -rf coreext_*.cc coreext_*.hh ghidraext_*.cc ghidraext_*.hh consoleext_*.cc consoleext_*.hh
|
||||||
rm -rf com_dbg com_opt ghi_dbg ghi_opt sla_dbg sla_opt
|
rm -rf com_dbg com_opt test_dbg ghi_dbg ghi_opt sla_dbg sla_opt
|
||||||
rm -f $(EXECS) TAGS *~
|
rm -f $(EXECS) TAGS *~
|
||||||
|
|
||||||
|
|
|
@ -223,7 +223,6 @@ double FloatFormat::getHostFloat(uintb encoding,floatclass *type) const
|
||||||
if (exp == 0) {
|
if (exp == 0) {
|
||||||
if ( frac == 0 ) { // Floating point zero
|
if ( frac == 0 ) { // Floating point zero
|
||||||
*type = zero;
|
*type = zero;
|
||||||
// FIXME: add on sign-bit for +0 or -0 allowed by standard
|
|
||||||
return sgn ? -0.0 : +0.0;
|
return sgn ? -0.0 : +0.0;
|
||||||
}
|
}
|
||||||
*type = denormalized;
|
*type = denormalized;
|
||||||
|
@ -233,7 +232,6 @@ double FloatFormat::getHostFloat(uintb encoding,floatclass *type) const
|
||||||
else if (exp == maxexponent) {
|
else if (exp == maxexponent) {
|
||||||
if ( frac == 0 ) { // Floating point infinity
|
if ( frac == 0 ) { // Floating point infinity
|
||||||
*type = infinity;
|
*type = infinity;
|
||||||
// FIXME: add on sign-bit for +inf or -inf allowed by standard
|
|
||||||
return sgn ? -INFINITY : +INFINITY;
|
return sgn ? -INFINITY : +INFINITY;
|
||||||
}
|
}
|
||||||
*type = nan;
|
*type = nan;
|
||||||
|
@ -254,6 +252,27 @@ double FloatFormat::getHostFloat(uintb encoding,floatclass *type) const
|
||||||
return createFloat(sgn,frac,exp);
|
return createFloat(sgn,frac,exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Round a floating point value to the nearest even
|
||||||
|
///
|
||||||
|
/// \param signif the significant bits of a floating point value
|
||||||
|
/// \param lowbitpos the position in signif of the floating point
|
||||||
|
/// \return true if we rounded up
|
||||||
|
|
||||||
|
bool FloatFormat::roundToNearestEven(uintb &signif, int4 lowbitpos)
|
||||||
|
|
||||||
|
{
|
||||||
|
uintb lowbitmask = (lowbitpos < 8 * sizeof(uintb)) ? (1UL << lowbitpos) : 0;
|
||||||
|
uintb midbitmask = 1UL << (lowbitpos - 1);
|
||||||
|
uintb epsmask = midbitmask - 1;
|
||||||
|
bool odd = (signif & lowbitmask) != 0;
|
||||||
|
if ((signif & midbitmask) != 0 && ((signif & epsmask) != 0 || odd)) {
|
||||||
|
signif += midbitmask;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \param host is the double value to convert
|
/// \param host is the double value to convert
|
||||||
/// \return the equivalent encoded value
|
/// \return the equivalent encoded value
|
||||||
uintb FloatFormat::getEncoding(double host) const
|
uintb FloatFormat::getEncoding(double host) const
|
||||||
|
@ -264,7 +283,7 @@ uintb FloatFormat::getEncoding(double host) const
|
||||||
uintb signif;
|
uintb signif;
|
||||||
int4 exp;
|
int4 exp;
|
||||||
|
|
||||||
type = extractExpSig(host,&sgn,&signif,&exp);
|
type = extractExpSig(host, &sgn, &signif, &exp);
|
||||||
if (type == zero)
|
if (type == zero)
|
||||||
return getZeroEncoding(sgn);
|
return getZeroEncoding(sgn);
|
||||||
else if (type == infinity)
|
else if (type == infinity)
|
||||||
|
@ -274,53 +293,114 @@ uintb FloatFormat::getEncoding(double host) const
|
||||||
|
|
||||||
// convert exponent and fractional to their encodings
|
// convert exponent and fractional to their encodings
|
||||||
exp += bias;
|
exp += bias;
|
||||||
if (exp < 0) // Exponent is too small to represent
|
|
||||||
return getZeroEncoding(sgn);
|
if (exp < -frac_size) // Exponent is too small to represent
|
||||||
if (exp > maxexponent) // Exponent is too big to represent
|
return getZeroEncoding(sgn); // TODO handle round to non-zero
|
||||||
|
|
||||||
|
if (exp < 1) { // Must be denormalized
|
||||||
|
if (roundToNearestEven(signif, 8 * sizeof(uintb) - frac_size - exp)) {
|
||||||
|
// TODO handle round to normal case
|
||||||
|
if ((signif >> (8 * sizeof(uintb) - 1)) == 0) {
|
||||||
|
signif = 1UL << (8 * sizeof(uintb) - 1);
|
||||||
|
exp += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uintb res = getZeroEncoding(sgn);
|
||||||
|
return setFractionalCode(res, signif >> (-exp));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roundToNearestEven(signif, 8 * sizeof(uintb) - frac_size - 1)) {
|
||||||
|
// if high bit is clear, then the add overflowed. Increase exp and set
|
||||||
|
// signif to 1.
|
||||||
|
if ((signif >> (8 * sizeof(uintb) - 1)) == 0) {
|
||||||
|
signif = 1UL << (8 * sizeof(uintb) - 1);
|
||||||
|
exp += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp >= maxexponent) // Exponent is too big to represent
|
||||||
return getInfinityEncoding(sgn);
|
return getInfinityEncoding(sgn);
|
||||||
if (jbitimplied && (exp !=0))
|
|
||||||
|
if (jbitimplied && (exp != 0))
|
||||||
signif <<= 1; // Cut off top bit (which should be 1)
|
signif <<= 1; // Cut off top bit (which should be 1)
|
||||||
|
|
||||||
uintb res = 0;
|
uintb res = 0;
|
||||||
res = setFractionalCode(res,signif);
|
res = setFractionalCode(res, signif);
|
||||||
res = setExponentCode(res,(uintb)exp);
|
res = setExponentCode(res, (uintb)exp);
|
||||||
return setSign(res,sgn);
|
return setSign(res, sgn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \param encoding is the value in the \e other FloatFormat
|
/// \param encoding is the value in the \e other FloatFormat
|
||||||
/// \param formin is the \e other FloatFormat
|
/// \param formin is the \e other FloatFormat
|
||||||
/// \return the equivalent value in \b this FloatFormat
|
/// \return the equivalent value in \b this FloatFormat
|
||||||
uintb FloatFormat::convertEncoding(uintb encoding,const FloatFormat *formin) const
|
uintb FloatFormat::convertEncoding(uintb encoding,
|
||||||
|
const FloatFormat *formin) const
|
||||||
|
|
||||||
{
|
{
|
||||||
bool sgn = formin->extractSign(encoding);
|
bool sgn = formin->extractSign(encoding);
|
||||||
uintb frac = formin->extractFractionalCode(encoding);
|
uintb signif = formin->extractFractionalCode(encoding);
|
||||||
int4 exp = formin->extractExponentCode(encoding);
|
int4 exp = formin->extractExponentCode(encoding);
|
||||||
|
|
||||||
if (exp == formin->maxexponent) { // NaN or INFINITY encoding
|
if (exp == formin->maxexponent) { // NaN or INFINITY encoding
|
||||||
exp = maxexponent;
|
exp = maxexponent;
|
||||||
}
|
if (signif != 0)
|
||||||
else {
|
return getNaNEncoding(sgn);
|
||||||
exp -= formin->bias;
|
else
|
||||||
exp += bias;
|
|
||||||
if (exp < 0)
|
|
||||||
return getZeroEncoding(sgn);
|
|
||||||
if (exp > maxexponent)
|
|
||||||
return getInfinityEncoding(sgn);
|
return getInfinityEncoding(sgn);
|
||||||
}
|
}
|
||||||
if (jbitimplied && !formin->jbitimplied)
|
|
||||||
frac <<= 1; // Cut off top bit (which should be 1)
|
if (exp == 0) { // incoming is subnormal
|
||||||
else if (formin->jbitimplied && !jbitimplied) {
|
if (signif == 0)
|
||||||
frac >>= 1; // Make room for 1 jbit
|
return getZeroEncoding(sgn);
|
||||||
uintb highbit = 1;
|
|
||||||
highbit <<= 8*sizeof(uintb)-1;
|
// normalize
|
||||||
frac |= highbit; // Stick bit in at top
|
int4 lz = count_leading_zeros(signif);
|
||||||
|
signif <<= lz;
|
||||||
|
exp = -formin->bias - lz;
|
||||||
|
}
|
||||||
|
else { // incoming is normal
|
||||||
|
exp -= formin->bias;
|
||||||
|
if (jbitimplied)
|
||||||
|
signif = (1UL << (8 * sizeof(uintb) - 1)) | (signif >> 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exp += bias;
|
||||||
|
|
||||||
|
if (exp < -frac_size) // Exponent is too small to represent
|
||||||
|
return getZeroEncoding(sgn); // TODO handle round to non-zero
|
||||||
|
|
||||||
|
if (exp < 1) { // Must be denormalized
|
||||||
|
if (roundToNearestEven(signif, 8 * sizeof(uintb) - frac_size - exp)) {
|
||||||
|
// TODO handle carry to normal case
|
||||||
|
if ((signif >> (8 * sizeof(uintb) - 1)) == 0) {
|
||||||
|
signif = 1UL << (8 * sizeof(uintb) - 1);
|
||||||
|
exp += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uintb res = getZeroEncoding(sgn);
|
||||||
|
return setFractionalCode(res, signif >> (-exp));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roundToNearestEven(signif, 8 * sizeof(uintb) - frac_size - 1)) {
|
||||||
|
// if high bit is clear, then the add overflowed. Increase exp and set
|
||||||
|
// signif to 1.
|
||||||
|
if ((signif >> (8 * sizeof(uintb) - 1)) == 0) {
|
||||||
|
signif = 1UL << (8 * sizeof(uintb) - 1);
|
||||||
|
exp += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp >= maxexponent) // Exponent is too big to represent
|
||||||
|
return getInfinityEncoding(sgn);
|
||||||
|
|
||||||
|
if (jbitimplied && (exp != 0))
|
||||||
|
signif <<= 1; // Cut off top bit (which should be 1)
|
||||||
|
|
||||||
uintb res = 0;
|
uintb res = 0;
|
||||||
res = setFractionalCode(res,frac);
|
res = setFractionalCode(res, signif);
|
||||||
res = setExponentCode(res,(uintb)exp);
|
res = setExponentCode(res, (uintb)exp);
|
||||||
return setSign(res,sgn);
|
return setSign(res, sgn);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently we emulate floating point operations on the target
|
// Currently we emulate floating point operations on the target
|
||||||
|
@ -487,9 +567,7 @@ uintb FloatFormat::opInt2Float(uintb a,int4 sizein) const
|
||||||
uintb FloatFormat::opFloat2Float(uintb a,const FloatFormat &outformat) const
|
uintb FloatFormat::opFloat2Float(uintb a,const FloatFormat &outformat) const
|
||||||
|
|
||||||
{
|
{
|
||||||
floatclass type;
|
return outformat.convertEncoding(a, this);
|
||||||
double val = getHostFloat(a,&type);
|
|
||||||
return outformat.getEncoding(val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param a is an encoded floating-point value
|
/// \param a is an encoded floating-point value
|
||||||
|
@ -533,7 +611,8 @@ uintb FloatFormat::opRound(uintb a) const
|
||||||
{
|
{
|
||||||
floatclass type;
|
floatclass type;
|
||||||
double val = getHostFloat(a,&type);
|
double val = getHostFloat(a,&type);
|
||||||
return getEncoding(floor(val+0.5));
|
// return getEncoding(floor(val+.5)); // round half up
|
||||||
|
return getEncoding(round(val)); // round half away from zero
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the format out to a \<floatformat> XML tag.
|
/// Write the format out to a \<floatformat> XML tag.
|
||||||
|
|
|
@ -50,6 +50,7 @@ private:
|
||||||
bool jbitimplied; ///< Set to \b true if integer bit of 1 is assumed
|
bool jbitimplied; ///< Set to \b true if integer bit of 1 is assumed
|
||||||
static double createFloat(bool sign,uintb signif,int4 exp); ///< Create a double given sign, fractional, and exponent
|
static double createFloat(bool sign,uintb signif,int4 exp); ///< Create a double given sign, fractional, and exponent
|
||||||
static floatclass extractExpSig(double x,bool *sgn,uintb *signif,int4 *exp);
|
static floatclass extractExpSig(double x,bool *sgn,uintb *signif,int4 *exp);
|
||||||
|
static bool roundToNearestEven(uintb &signif, int4 lowbitpos);
|
||||||
uintb setFractionalCode(uintb x,uintb code) const; ///< Set the fractional part of an encoded value
|
uintb setFractionalCode(uintb x,uintb code) const; ///< Set the fractional part of an encoded value
|
||||||
uintb setSign(uintb x,bool sign) const; ///< Set the sign bit of an encoded value
|
uintb setSign(uintb x,bool sign) const; ///< Set the sign bit of an encoded value
|
||||||
uintb setExponentCode(uintb x,uintb code) const; ///< Set the exponent of an encoded value
|
uintb setExponentCode(uintb x,uintb code) const; ///< Set the exponent of an encoded value
|
||||||
|
|
482
Ghidra/Features/Decompiler/src/decompile/cpp/test.cc
Normal file
482
Ghidra/Features/Decompiler/src/decompile/cpp/test.cc
Normal file
|
@ -0,0 +1,482 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
/// \file test.cc
|
||||||
|
/// \brief Unit tests for Ghidra C++ components.
|
||||||
|
|
||||||
|
#include "float.hh"
|
||||||
|
#include "opbehavior.hh"
|
||||||
|
#include "test.hh"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// utility functions
|
||||||
|
float floatFromRawBits(uintb e) {
|
||||||
|
float f;
|
||||||
|
memcpy(&f, &e, 4);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintb floatToRawBits(float f) {
|
||||||
|
uintb result = 0;
|
||||||
|
memcpy(&result, &f, 4);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
double doubleFromRawBits(uintb e) {
|
||||||
|
double f;
|
||||||
|
memcpy(&f, &e, 8);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintb doubleToRawBits(double f) {
|
||||||
|
uintb result = 0;
|
||||||
|
memcpy(&result, &f, 8);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// macros to preserve call site
|
||||||
|
#define ASSERT_FLOAT_ENCODING(f) \
|
||||||
|
do { \
|
||||||
|
FloatFormat format(4); \
|
||||||
|
\
|
||||||
|
uintb true_encoding = floatToRawBits(f); \
|
||||||
|
uintb encoding = format.getEncoding(f); \
|
||||||
|
\
|
||||||
|
ASSERT_EQUALS(true_encoding, encoding); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
#define ASSERT_DOUBLE_ENCODING(f) \
|
||||||
|
do { \
|
||||||
|
FloatFormat format(8); \
|
||||||
|
\
|
||||||
|
uintb true_encoding = doubleToRawBits(f); \
|
||||||
|
uintb encoding = format.getEncoding(f); \
|
||||||
|
\
|
||||||
|
ASSERT_EQUALS(true_encoding, encoding); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
//// FloatFormat tests
|
||||||
|
|
||||||
|
static std::vector<float> float_test_values{
|
||||||
|
-0.0f,
|
||||||
|
+0.0f,
|
||||||
|
-1.0f,
|
||||||
|
+1.0f,
|
||||||
|
|
||||||
|
-1.234f,
|
||||||
|
+1.234f,
|
||||||
|
|
||||||
|
-std::numeric_limits<float>::denorm_min(),
|
||||||
|
std::numeric_limits<float>::denorm_min(),
|
||||||
|
|
||||||
|
std::numeric_limits<float>::min() - std::numeric_limits<float>::denorm_min(),
|
||||||
|
std::numeric_limits<float>::min(),
|
||||||
|
std::numeric_limits<float>::min() + std::numeric_limits<float>::denorm_min(),
|
||||||
|
|
||||||
|
-std::numeric_limits<float>::min() + std::numeric_limits<float>::denorm_min(),
|
||||||
|
-std::numeric_limits<float>::min(),
|
||||||
|
-std::numeric_limits<float>::min() - std::numeric_limits<float>::denorm_min(),
|
||||||
|
|
||||||
|
std::numeric_limits<float>::max(),
|
||||||
|
|
||||||
|
std::numeric_limits<float>::quiet_NaN(),
|
||||||
|
|
||||||
|
-std::numeric_limits<float>::infinity(),
|
||||||
|
std::numeric_limits<float>::infinity()
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::vector<int> int_test_values = {
|
||||||
|
0, -1, 1, 1234, -1234, std::numeric_limits<int>::min(), std::numeric_limits<int>::max()
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(float_encoding_normal) {
|
||||||
|
ASSERT_FLOAT_ENCODING(1.234);
|
||||||
|
ASSERT_FLOAT_ENCODING(-1.234);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(double_encoding_normal) {
|
||||||
|
ASSERT_DOUBLE_ENCODING(1.234);
|
||||||
|
ASSERT_DOUBLE_ENCODING(-1.234);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(float_encoding_nan) {
|
||||||
|
ASSERT_FLOAT_ENCODING(std::numeric_limits<float>::quiet_NaN());
|
||||||
|
ASSERT_FLOAT_ENCODING(-std::numeric_limits<float>::quiet_NaN());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(double_encoding_nan) {
|
||||||
|
ASSERT_DOUBLE_ENCODING(std::numeric_limits<double>::quiet_NaN());
|
||||||
|
ASSERT_DOUBLE_ENCODING(-std::numeric_limits<double>::quiet_NaN());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(float_encoding_subnormal) {
|
||||||
|
ASSERT_FLOAT_ENCODING(std::numeric_limits<float>::denorm_min());
|
||||||
|
ASSERT_FLOAT_ENCODING(-std::numeric_limits<float>::denorm_min());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(double_encoding_subnormal) {
|
||||||
|
ASSERT_DOUBLE_ENCODING(std::numeric_limits<double>::denorm_min());
|
||||||
|
ASSERT_DOUBLE_ENCODING(-std::numeric_limits<double>::denorm_min());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(float_encoding_min_normal) {
|
||||||
|
ASSERT_FLOAT_ENCODING(std::numeric_limits<float>::min());
|
||||||
|
ASSERT_FLOAT_ENCODING(-std::numeric_limits<float>::min());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(double_encoding_min_normal) {
|
||||||
|
ASSERT_DOUBLE_ENCODING(std::numeric_limits<double>::min());
|
||||||
|
ASSERT_DOUBLE_ENCODING(-std::numeric_limits<double>::min());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(float_encoding_infinity) {
|
||||||
|
ASSERT_FLOAT_ENCODING(std::numeric_limits<float>::infinity());
|
||||||
|
ASSERT_FLOAT_ENCODING(-std::numeric_limits<float>::infinity());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(double_encoding_infinity) {
|
||||||
|
ASSERT_DOUBLE_ENCODING(std::numeric_limits<double>::infinity());
|
||||||
|
ASSERT_DOUBLE_ENCODING(-std::numeric_limits<double>::infinity());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(float_midpoint_rounding) {
|
||||||
|
FloatFormat ff(4);
|
||||||
|
// IEEE754 recommends "round to nearest even" for binary formats, like single and double
|
||||||
|
// precision floating point. It rounds to the nearest integer (significand) when unambiguous,
|
||||||
|
// and to the nearest even on the midpoint.
|
||||||
|
|
||||||
|
// There are 52 bits of significand in a double and 23 in a float.
|
||||||
|
// Below we construct a sequence of double precision values to demonstrate each case
|
||||||
|
// in rounding,
|
||||||
|
|
||||||
|
// d0 - zeros in low 29 bits, round down
|
||||||
|
// d1 - on the rounding midpoint with integer even integer part, round down
|
||||||
|
// d2 - just above the midpoint, round up
|
||||||
|
double d0 = doubleFromRawBits(0x4010000000000000L);
|
||||||
|
double d1 = doubleFromRawBits(0x4010000010000000L);
|
||||||
|
double d2 = doubleFromRawBits(0x4010000010000001L);
|
||||||
|
|
||||||
|
// d3 - zeros in low 29 bits, round down
|
||||||
|
// d4 - on the rounding midpoint with integer part odd, round up
|
||||||
|
// d5 - just above the midpoint, round up
|
||||||
|
double d3 = doubleFromRawBits(0x4010000020000000L);
|
||||||
|
double d4 = doubleFromRawBits(0x4010000030000000L);
|
||||||
|
double d5 = doubleFromRawBits(0x4010000030000001L);
|
||||||
|
|
||||||
|
float f0 = (float)d0;
|
||||||
|
float f1 = (float)d1;
|
||||||
|
float f2 = (float)d2;
|
||||||
|
float f3 = (float)d3;
|
||||||
|
float f4 = (float)d4;
|
||||||
|
float f5 = (float)d5;
|
||||||
|
|
||||||
|
uintb e0 = ff.getEncoding(d0);
|
||||||
|
uintb e1 = ff.getEncoding(d1);
|
||||||
|
uintb e2 = ff.getEncoding(d2);
|
||||||
|
uintb e3 = ff.getEncoding(d3);
|
||||||
|
uintb e4 = ff.getEncoding(d4);
|
||||||
|
uintb e5 = ff.getEncoding(d5);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(floatToRawBits(f0), e0);
|
||||||
|
ASSERT_EQUALS(floatToRawBits(f1), e1);
|
||||||
|
ASSERT_EQUALS(floatToRawBits(f2), e2);
|
||||||
|
ASSERT_EQUALS(floatToRawBits(f3), e3);
|
||||||
|
ASSERT_EQUALS(floatToRawBits(f4), e4);
|
||||||
|
ASSERT_EQUALS(floatToRawBits(f5), e5);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(e0, e1);
|
||||||
|
ASSERT_NOT_EQUALS(e1, e2);
|
||||||
|
|
||||||
|
ASSERT_NOT_EQUALS(e3, e4);
|
||||||
|
ASSERT_EQUALS(e4, e5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// op tests
|
||||||
|
|
||||||
|
// generated
|
||||||
|
|
||||||
|
TEST(float_opNan) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f:float_test_values) {
|
||||||
|
uintb true_result = isnan(f);
|
||||||
|
uintb encoding = format.getEncoding(f);
|
||||||
|
uintb result = format.opNan(encoding);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opNeg) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f:float_test_values) {
|
||||||
|
uintb true_result = floatToRawBits(-f);
|
||||||
|
uintb encoding = format.getEncoding(f);
|
||||||
|
uintb result = format.opNeg(encoding);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opAbs) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f:float_test_values) {
|
||||||
|
uintb true_result = floatToRawBits(abs(f));
|
||||||
|
uintb encoding = format.getEncoding(f);
|
||||||
|
uintb result = format.opAbs(encoding);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opSqrt) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f:float_test_values) {
|
||||||
|
uintb true_result = floatToRawBits(sqrtf(f));
|
||||||
|
uintb encoding = format.getEncoding(f);
|
||||||
|
uintb result = format.opSqrt(encoding);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opCeil) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f:float_test_values) {
|
||||||
|
uintb true_result = floatToRawBits(ceilf(f));
|
||||||
|
uintb encoding = format.getEncoding(f);
|
||||||
|
uintb result = format.opCeil(encoding);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opFloor) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f:float_test_values) {
|
||||||
|
uintb true_result = floatToRawBits(floorf(f));
|
||||||
|
uintb encoding = format.getEncoding(f);
|
||||||
|
uintb result = format.opFloor(encoding);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opRound) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f:float_test_values) {
|
||||||
|
uintb true_result = floatToRawBits(roundf(f));
|
||||||
|
uintb encoding = format.getEncoding(f);
|
||||||
|
uintb result = format.opRound(encoding);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opInt2Float_size4) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(int i:int_test_values) {
|
||||||
|
uintb true_result = floatToRawBits((float)i);
|
||||||
|
uintb result = format.opInt2Float(i, 4);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO other sized ints
|
||||||
|
|
||||||
|
TEST(float_to_double_opFloat2Float) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
FloatFormat format8(8);
|
||||||
|
|
||||||
|
for(float f:float_test_values) {
|
||||||
|
uintb true_result = doubleToRawBits((double)f);
|
||||||
|
uintb encoding = format.getEncoding(f);
|
||||||
|
uintb result = format.opFloat2Float(encoding, format8);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO float2float going the other direction, double_to_float_opFloat2Float
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opTrunc_to_int) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
FloatFormat format8(8);
|
||||||
|
|
||||||
|
for(float f:float_test_values) {
|
||||||
|
// avoid undefined behavior
|
||||||
|
if((int64_t)f > std::numeric_limits<int>::max() || (int64_t)f < std::numeric_limits<int>::min())
|
||||||
|
continue;
|
||||||
|
uintb true_result = ((uintb)(int32_t)f) & 0xffffffff;
|
||||||
|
uintb encoding = format.getEncoding(f);
|
||||||
|
uintb result = format.opTrunc(encoding, 4);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO trunc to other sizes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opEqual) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f1:float_test_values) {
|
||||||
|
uintb encoding1 = format.getEncoding(f1);
|
||||||
|
for(float f2:float_test_values) {
|
||||||
|
uintb true_result = (f1==f2);
|
||||||
|
uintb encoding2 = format.getEncoding(f2);
|
||||||
|
uintb result = format.opEqual(encoding1, encoding2);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opNotEqual) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f1:float_test_values) {
|
||||||
|
uintb encoding1 = format.getEncoding(f1);
|
||||||
|
for(float f2:float_test_values) {
|
||||||
|
uintb true_result = (f1!=f2);
|
||||||
|
uintb encoding2 = format.getEncoding(f2);
|
||||||
|
uintb result = format.opNotEqual(encoding1, encoding2);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opLess) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f1:float_test_values) {
|
||||||
|
uintb encoding1 = format.getEncoding(f1);
|
||||||
|
for(float f2:float_test_values) {
|
||||||
|
uintb true_result = (f1<f2);
|
||||||
|
uintb encoding2 = format.getEncoding(f2);
|
||||||
|
uintb result = format.opLess(encoding1, encoding2);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opLessEqual) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f1:float_test_values) {
|
||||||
|
uintb encoding1 = format.getEncoding(f1);
|
||||||
|
for(float f2:float_test_values) {
|
||||||
|
uintb true_result = (f1<=f2);
|
||||||
|
uintb encoding2 = format.getEncoding(f2);
|
||||||
|
uintb result = format.opLessEqual(encoding1, encoding2);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opAdd) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f1:float_test_values) {
|
||||||
|
uintb encoding1 = format.getEncoding(f1);
|
||||||
|
for(float f2:float_test_values) {
|
||||||
|
uintb true_result = floatToRawBits(f1+f2);
|
||||||
|
uintb encoding2 = format.getEncoding(f2);
|
||||||
|
uintb result = format.opAdd(encoding1, encoding2);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opDiv) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f1:float_test_values) {
|
||||||
|
uintb encoding1 = format.getEncoding(f1);
|
||||||
|
for(float f2:float_test_values) {
|
||||||
|
uintb true_result = floatToRawBits(f1/f2);
|
||||||
|
uintb encoding2 = format.getEncoding(f2);
|
||||||
|
uintb result = format.opDiv(encoding1, encoding2);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opMult) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f1:float_test_values) {
|
||||||
|
uintb encoding1 = format.getEncoding(f1);
|
||||||
|
for(float f2:float_test_values) {
|
||||||
|
uintb true_result = floatToRawBits(f1*f2);
|
||||||
|
uintb encoding2 = format.getEncoding(f2);
|
||||||
|
uintb result = format.opMult(encoding1, encoding2);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(float_opSub) {
|
||||||
|
FloatFormat format(4);
|
||||||
|
|
||||||
|
for(float f1:float_test_values) {
|
||||||
|
uintb encoding1 = format.getEncoding(f1);
|
||||||
|
for(float f2:float_test_values) {
|
||||||
|
uintb true_result = floatToRawBits(f1-f2);
|
||||||
|
uintb encoding2 = format.getEncoding(f2);
|
||||||
|
uintb result = format.opSub(encoding1, encoding2);
|
||||||
|
|
||||||
|
ASSERT_EQUALS(true_result, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// end generated
|
105
Ghidra/Features/Decompiler/src/decompile/cpp/test.hh
Normal file
105
Ghidra/Features/Decompiler/src/decompile/cpp/test.hh
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
/// \file test.hh
|
||||||
|
/// \brief Simple test framework
|
||||||
|
///
|
||||||
|
/// Include this file and any additional headers. Use TEST(testname) as
|
||||||
|
/// prototype in test function definitions. E.g.
|
||||||
|
/// test.cc:
|
||||||
|
/// #include "float.hh"
|
||||||
|
/// #include "test.hh"
|
||||||
|
///
|
||||||
|
/// TEST(zero_is_less_than_one) {
|
||||||
|
/// ASSERT(0.0 < 1.0);
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct Test;
|
||||||
|
typedef void (*testfunc_t)();
|
||||||
|
|
||||||
|
std::vector<Test *> tests;
|
||||||
|
|
||||||
|
struct Test {
|
||||||
|
std::string name;
|
||||||
|
testfunc_t func;
|
||||||
|
|
||||||
|
Test(const std::string &name, testfunc_t func) : name(name), func(func) {
|
||||||
|
tests.push_back(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#define TEST(testname) \
|
||||||
|
void testname(); \
|
||||||
|
Test testname##_obj{ #testname, testname }; \
|
||||||
|
void testname()
|
||||||
|
|
||||||
|
#define ASSERT(test) \
|
||||||
|
if (!(test)) { \
|
||||||
|
std::cerr << " failed at " << __FILE__ << ":" << __LINE__ << " asserting \"" << #test << "\"." << std::endl; \
|
||||||
|
throw 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSERT_EQUALS(a, b) \
|
||||||
|
if ((a) != (b)) { \
|
||||||
|
std::stringstream ssa, ssb; \
|
||||||
|
ssa << (a); \
|
||||||
|
ssb << (b); \
|
||||||
|
std::cerr << " failed at " << __FILE__ << ":" << __LINE__ << " asserting \"" << ssa.str() \
|
||||||
|
<< " == " << ssb.str() << "\"." << std::endl; \
|
||||||
|
throw 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSERT_NOT_EQUALS(a, b) \
|
||||||
|
if ((a) == (b)) { \
|
||||||
|
std::stringstream ssa, ssb; \
|
||||||
|
ssa << (a); \
|
||||||
|
ssb << (b); \
|
||||||
|
std::cerr << " failed at " << __FILE__ << ":" << __LINE__ << " asserting \"" << ssa.str() \
|
||||||
|
<< " != " << ssb.str() << "\"." << std::endl; \
|
||||||
|
throw 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int total = 0;
|
||||||
|
int passed = 0;
|
||||||
|
|
||||||
|
std::set<std::string> testnames(argv + 1, argv + argc);
|
||||||
|
|
||||||
|
for (auto &t : tests) {
|
||||||
|
if(testnames.size()>0 && testnames.find(t->name)==testnames.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::cerr << "testing : " << t->name << " ..." << std::endl;
|
||||||
|
++total;
|
||||||
|
try {
|
||||||
|
t->func();
|
||||||
|
++passed;
|
||||||
|
std::cerr << " passed." << std::endl;
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cerr << "==============================" << std::endl;
|
||||||
|
std::cerr << passed << "/" << total << " tests passed." << std::endl;
|
||||||
|
}
|
|
@ -78,7 +78,8 @@ public class SpecifyCPrototypeAction extends AbstractDecompilerAction {
|
||||||
if (!useCustom) {
|
if (!useCustom) {
|
||||||
// remove original params which replicate auto params
|
// remove original params which replicate auto params
|
||||||
for (int i = 0; i < autoParamCnt; i++) {
|
for (int i = 0; i < autoParamCnt; i++) {
|
||||||
model.setSelectedParameterRow(new int[] { autoParamCnt });
|
// be sure to select beyond auto-params. First auto-param is on row 1
|
||||||
|
model.setSelectedParameterRow(new int[] { autoParamCnt + 1 });
|
||||||
model.removeParameters();
|
model.removeParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,993 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.pcode.floatformat;
|
||||||
|
|
||||||
|
import java.math.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An IEEE 754 floating point class.
|
||||||
|
*
|
||||||
|
* <p>Values represented:
|
||||||
|
* <ul>
|
||||||
|
* <li>QUIET_NAN, SIGNALED_NAN</li>
|
||||||
|
* <li>-INF, +INF</li>
|
||||||
|
* <li>value = sign * unscaled * 2 ^ (scale-fracbits)</li>
|
||||||
|
* </ul>
|
||||||
|
* sign = -1 or +1, unscaled has at most fracbits+1 bits, and scale is at most expbits bits.
|
||||||
|
*
|
||||||
|
* <p>Operations compute exact result then round to nearest even.
|
||||||
|
*/
|
||||||
|
public strictfp class BigFloat implements Comparable<BigFloat> {
|
||||||
|
final int fracbits; // there are fracbits+1 significant bits.
|
||||||
|
final int expbits; // # bits used for exponent
|
||||||
|
|
||||||
|
final int maxScale;
|
||||||
|
final int minScale;
|
||||||
|
|
||||||
|
FloatKind kind;
|
||||||
|
|
||||||
|
// -1, +1
|
||||||
|
int sign;
|
||||||
|
// normal numbers have unscaled.bitLength() = fracbits+1
|
||||||
|
// subnormal numbers have scale=0 and unscaled.bitLength() <= fracbits
|
||||||
|
BigInteger unscaled;
|
||||||
|
int scale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a BigFloat. If kind is FINITE, the value is <code>sign*unscaled*2^(scale-fracbits)</code>
|
||||||
|
*
|
||||||
|
* @param fracbits number of fractional bits
|
||||||
|
* @param expbits maximum number of bits in exponent
|
||||||
|
* @param kind the Kind, FINITE, INFINITE, ...
|
||||||
|
* @param sign +1 or -1
|
||||||
|
* @param unscaled the value's mantissa
|
||||||
|
* @param scale value's scale
|
||||||
|
*/
|
||||||
|
public BigFloat(int fracbits, int expbits, FloatKind kind, int sign, BigInteger unscaled,
|
||||||
|
int scale) {
|
||||||
|
this.fracbits = fracbits;
|
||||||
|
this.expbits = expbits;
|
||||||
|
this.kind = kind;
|
||||||
|
this.sign = sign;
|
||||||
|
this.unscaled = unscaled;
|
||||||
|
this.scale = scale;
|
||||||
|
|
||||||
|
this.maxScale = (1 << (expbits - 1)) - 1;
|
||||||
|
this.minScale = 1 - this.maxScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + expbits;
|
||||||
|
result = prime * result + fracbits;
|
||||||
|
result = prime * result + kind.hashCode();
|
||||||
|
switch (kind) {
|
||||||
|
case FINITE:
|
||||||
|
result = prime * result + sign;
|
||||||
|
result = prime * result + scale;
|
||||||
|
result = prime * result + unscaled.hashCode();
|
||||||
|
break;
|
||||||
|
case INFINITE:
|
||||||
|
result = prime * result + sign;
|
||||||
|
break;
|
||||||
|
case QUIET_NAN:
|
||||||
|
case SIGNALING_NAN:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
BigFloat other = (BigFloat) obj;
|
||||||
|
if (expbits != other.expbits) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fracbits != other.fracbits) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (kind != other.kind) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (kind) {
|
||||||
|
case FINITE:
|
||||||
|
if (sign != other.sign) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (scale != other.scale) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!unscaled.equals(other.unscaled)) {
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case INFINITE:
|
||||||
|
if (sign != other.sign) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QUIET_NAN:
|
||||||
|
case SIGNALING_NAN:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @param fracbits number of fractional bits
|
||||||
|
* @param expbits number of bits in the exponent
|
||||||
|
* @param sign +1 or -1
|
||||||
|
* @return a BigFloat representing +zero or -zero
|
||||||
|
*/
|
||||||
|
public static BigFloat zero(int fracbits, int expbits, int sign) {
|
||||||
|
return new BigFloat(fracbits, expbits, FloatKind.FINITE, sign, BigInteger.ZERO,
|
||||||
|
2 - (1 << (expbits - 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the BigFloat with the given number of bits representing (positive) zero.
|
||||||
|
*
|
||||||
|
* @param fracbits number of fractional bits
|
||||||
|
* @param expbits number of bits in the exponent
|
||||||
|
* @return a BigFloat representing +zero
|
||||||
|
*/
|
||||||
|
public static BigFloat zero(int fracbits, int expbits) {
|
||||||
|
return zero(fracbits, expbits, +1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param fracbits number of fractional bits
|
||||||
|
* @param expbits number of bits in the exponent
|
||||||
|
* @param sign +1 or -1
|
||||||
|
* @return +inf or -inf
|
||||||
|
*/
|
||||||
|
public static BigFloat infinity(int fracbits, int expbits, int sign) {
|
||||||
|
return new BigFloat(fracbits, expbits, FloatKind.INFINITE, sign,
|
||||||
|
BigInteger.ONE.shiftLeft(fracbits), (1 << (expbits - 1)) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the BigFloat with the given number of bits representing (quiet) NaN.
|
||||||
|
*
|
||||||
|
* @param fracbits number of fractional bits
|
||||||
|
* @param expbits number of bits in the exponent
|
||||||
|
* @param sign +1 or -1
|
||||||
|
* @return a BigFloat representing (quiet) NaN
|
||||||
|
*/
|
||||||
|
public static BigFloat quietNaN(int fracbits, int expbits, int sign) {
|
||||||
|
return new BigFloat(fracbits, expbits, FloatKind.QUIET_NAN, sign, BigInteger.ZERO,
|
||||||
|
(1 << (expbits - 1)) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void upscale(int nbits) {
|
||||||
|
unscaled = unscaled.shiftLeft(nbits);
|
||||||
|
scale -= nbits;
|
||||||
|
}
|
||||||
|
|
||||||
|
// guarantee at least significant bits (fractbits+1) plus one for rounding
|
||||||
|
protected void scaleUpTo(int newLength) {
|
||||||
|
if (kind != FloatKind.FINITE) {
|
||||||
|
throw new AssertionError("scaling of non-finite float!");
|
||||||
|
}
|
||||||
|
int d = newLength - this.unscaled.bitLength();
|
||||||
|
if (d > 0) {
|
||||||
|
this.upscale(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@code true} if this BigFloat is FINITE and normal
|
||||||
|
*/
|
||||||
|
public boolean isNormal() {
|
||||||
|
return kind == FloatKind.FINITE && unscaled.bitLength() >= fracbits + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is used internally to round after a computation.
|
||||||
|
*
|
||||||
|
* <p>Assume that the true value is
|
||||||
|
* <code>sign * (unscaled + eps) * 2 ^ (scale-fracbits)</code>
|
||||||
|
* and
|
||||||
|
* <code>unscaled.bitLength() > fracbits+1</code>
|
||||||
|
* (or the value is subnormal with at least 1 bit of extra precision)
|
||||||
|
*
|
||||||
|
* @param eps < 1
|
||||||
|
*/
|
||||||
|
protected void internalRound(boolean eps) {
|
||||||
|
if (kind != FloatKind.FINITE) {
|
||||||
|
throw new AssertionError("Rounding non-finite float");
|
||||||
|
}
|
||||||
|
if (unscaled.signum() == 0) {
|
||||||
|
if (eps) {
|
||||||
|
throw new AssertionError("Rounding zero + epsilon, need bit length");
|
||||||
|
}
|
||||||
|
makeZero();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int extrabits = Math.max(unscaled.bitLength() - (fracbits + 1), minScale - scale);
|
||||||
|
|
||||||
|
if (extrabits <= 0) {
|
||||||
|
throw new AssertionError("Rounding with no extra bits of precision");
|
||||||
|
}
|
||||||
|
|
||||||
|
int midbit = extrabits - 1;
|
||||||
|
boolean midbitset = this.unscaled.testBit(midbit);
|
||||||
|
eps |= unscaled.getLowestSetBit() < midbit;
|
||||||
|
unscaled = unscaled.shiftRight(extrabits);
|
||||||
|
scale += extrabits;
|
||||||
|
boolean odd = unscaled.testBit(0);
|
||||||
|
|
||||||
|
if (midbitset && (eps || odd)) {
|
||||||
|
unscaled = unscaled.add(BigInteger.ONE);
|
||||||
|
// handle overflowing carry
|
||||||
|
if (unscaled.bitLength() > fracbits + 1) {
|
||||||
|
assert (unscaled.bitLength() == unscaled.getLowestSetBit() + 1);
|
||||||
|
unscaled = unscaled.shiftRight(1);
|
||||||
|
scale += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scale > maxScale) {
|
||||||
|
kind = FloatKind.INFINITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getLeadBitPos() {
|
||||||
|
if (kind != FloatKind.FINITE || unscaled.signum() == 0) {
|
||||||
|
throw new AssertionError("lead bit of non-finite or zero");
|
||||||
|
}
|
||||||
|
return unscaled.bitLength() - fracbits + scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If finite, the returned BigDecimal is exactly equal to this. If not finite, one of the
|
||||||
|
* FloatFormat.BIG_* constants is returned.
|
||||||
|
*
|
||||||
|
* @return a BigDecimal
|
||||||
|
*/
|
||||||
|
public BigDecimal toBigDecimal() {
|
||||||
|
switch (kind) {
|
||||||
|
case FINITE:
|
||||||
|
// sign * unscaled * 2^(scale-fracbits)
|
||||||
|
int iscale = scale - fracbits;
|
||||||
|
BigDecimal x;
|
||||||
|
if (iscale >= 0) {
|
||||||
|
x = new BigDecimal(unscaled.shiftLeft(iscale));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
x = new BigDecimal(unscaled.multiply(BigInteger.valueOf(5).pow(-iscale)),
|
||||||
|
-iscale);
|
||||||
|
}
|
||||||
|
if (sign < 0) {
|
||||||
|
x = x.negate();
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
case INFINITE:
|
||||||
|
return sign < 0 ? FloatFormat.BIG_NEGATIVE_INFINITY
|
||||||
|
: FloatFormat.BIG_POSITIVE_INFINITY;
|
||||||
|
case QUIET_NAN:
|
||||||
|
case SIGNALING_NAN:
|
||||||
|
return FloatFormat.BIG_NaN;
|
||||||
|
default:
|
||||||
|
throw new AssertionError("unknown BigFloat kind: " + kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toBinaryString() {
|
||||||
|
switch (kind) {
|
||||||
|
case QUIET_NAN:
|
||||||
|
return "qNaN";
|
||||||
|
case SIGNALING_NAN:
|
||||||
|
return "sNaN";
|
||||||
|
case INFINITE:
|
||||||
|
if (sign < 0)
|
||||||
|
return "-inf";
|
||||||
|
return "+inf";
|
||||||
|
case FINITE:
|
||||||
|
String s = (sign < 0) ? "-" : "";
|
||||||
|
|
||||||
|
int ascale = scale;
|
||||||
|
|
||||||
|
String binary;
|
||||||
|
if (this.isNormal()) {
|
||||||
|
binary = "1." + unscaled.toString(2).substring(1);
|
||||||
|
ascale += (unscaled.bitLength() - (fracbits + 1));
|
||||||
|
}
|
||||||
|
else { // subnormal
|
||||||
|
assert (unscaled.bitLength() <= fracbits);
|
||||||
|
if (unscaled.equals(BigInteger.ZERO)) {
|
||||||
|
return String.format("%s0b0.0", s);
|
||||||
|
}
|
||||||
|
binary =
|
||||||
|
"0." + "0".repeat(fracbits - unscaled.bitLength()) + unscaled.toString(2);
|
||||||
|
}
|
||||||
|
binary = binary.replaceAll("0*$", "");
|
||||||
|
if (binary.endsWith(".")) {
|
||||||
|
binary += "0";
|
||||||
|
}
|
||||||
|
return String.format("%s0b%s * 2^%d", s, binary, ascale);
|
||||||
|
default:
|
||||||
|
throw new AssertionError("unexpected kind " + kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void makeSignalingNaN() {
|
||||||
|
this.kind = FloatKind.SIGNALING_NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void makeQuietNaN() {
|
||||||
|
this.kind = FloatKind.QUIET_NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@code true} if this BigFloat is NaN
|
||||||
|
*/
|
||||||
|
public boolean isNaN() {
|
||||||
|
return kind == FloatKind.QUIET_NAN || kind == FloatKind.SIGNALING_NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void makeZero() {
|
||||||
|
this.kind = FloatKind.FINITE;
|
||||||
|
this.unscaled = BigInteger.ZERO;
|
||||||
|
this.scale = minScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@code true} if this BigFloat is infinite
|
||||||
|
*/
|
||||||
|
public boolean isInfinite() {
|
||||||
|
return kind == FloatKind.INFINITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@code true} if this BigFloat is zero
|
||||||
|
*/
|
||||||
|
public boolean isZero() {
|
||||||
|
return this.kind == FloatKind.FINITE && unscaled.equals(BigInteger.ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a copy of this BigFloat
|
||||||
|
*/
|
||||||
|
public BigFloat copy() {
|
||||||
|
return new BigFloat(fracbits, expbits, kind, sign, unscaled, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
// assuming same fracbits and expbits...
|
||||||
|
protected void copyFrom(BigFloat other) {
|
||||||
|
this.kind = other.kind;
|
||||||
|
this.sign = other.sign;
|
||||||
|
this.unscaled = other.unscaled;
|
||||||
|
this.scale = other.scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param a a BigFloat
|
||||||
|
* @param b a BigFloat
|
||||||
|
* @return {@code a/b}
|
||||||
|
*/
|
||||||
|
public static BigFloat div(BigFloat a, BigFloat b) {
|
||||||
|
BigFloat c = a.copy();
|
||||||
|
c.div(b);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code this/=other}
|
||||||
|
*
|
||||||
|
* @param other a BigFloat
|
||||||
|
*/
|
||||||
|
public void div(BigFloat other) {
|
||||||
|
if (this.isNaN() || other.isNaN()) {
|
||||||
|
makeQuietNaN();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isInfinite()) {
|
||||||
|
if (other.isInfinite()) {
|
||||||
|
makeQuietNaN();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sign *= other.sign;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is finite
|
||||||
|
switch (other.kind) {
|
||||||
|
case QUIET_NAN:
|
||||||
|
case SIGNALING_NAN:
|
||||||
|
this.makeQuietNaN();
|
||||||
|
return;
|
||||||
|
case INFINITE:
|
||||||
|
makeZero();
|
||||||
|
sign *= other.sign;
|
||||||
|
return;
|
||||||
|
case FINITE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new AssertionError("unexpected kind " + other.kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (other.isZero()) {
|
||||||
|
if (this.isZero()) {
|
||||||
|
makeQuietNaN();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.kind = FloatKind.INFINITE;
|
||||||
|
this.sign *= other.sign;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// this is finite, other is finite non zero
|
||||||
|
|
||||||
|
// update representations so that this.unscaled has at fracbits+2 -- normal precision plus one for rounding.
|
||||||
|
//
|
||||||
|
// for numbers a,b
|
||||||
|
// floor(a)-floor(b)-1 <= floor(a-b) <= floor(a)-floor(b)
|
||||||
|
// nbits(x) = floor(log_2(x))+1, so
|
||||||
|
// nbits(x) - nbits(y) <= nbits(x/y) <= nbits(x) - nbits(y) + 1
|
||||||
|
// so
|
||||||
|
// this + lshift - other = fracbits+2 =>
|
||||||
|
int lshift = fracbits + 2 + other.unscaled.bitLength() - this.unscaled.bitLength();
|
||||||
|
this.upscale(lshift);
|
||||||
|
|
||||||
|
BigInteger qr[] = this.unscaled.divideAndRemainder(other.unscaled);
|
||||||
|
BigInteger q = qr[0];
|
||||||
|
BigInteger r = qr[1];
|
||||||
|
|
||||||
|
this.sign *= other.sign;
|
||||||
|
this.scale -= other.scale - fracbits;
|
||||||
|
this.unscaled = q;
|
||||||
|
this.internalRound(r.signum() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param a a BigFloat
|
||||||
|
* @param b a BigFloat
|
||||||
|
* @return {@code a*b}
|
||||||
|
*/
|
||||||
|
public static BigFloat mul(BigFloat a, BigFloat b) {
|
||||||
|
BigFloat c = a.copy();
|
||||||
|
c.mul(b);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code this*=other}
|
||||||
|
*
|
||||||
|
* @param other a BigFloat
|
||||||
|
*/
|
||||||
|
public void mul(BigFloat other) {
|
||||||
|
if (this.isNaN() || other.isNaN()) {
|
||||||
|
this.makeQuietNaN();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((this.isZero() && other.isInfinite()) || (this.isInfinite() && other.isZero())) {
|
||||||
|
this.makeQuietNaN();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isInfinite() || other.isInfinite()) {
|
||||||
|
this.kind = FloatKind.INFINITE;
|
||||||
|
this.sign *= other.sign;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this and other are finite
|
||||||
|
this.sign *= other.sign;
|
||||||
|
this.unscaled = this.unscaled.multiply(other.unscaled);
|
||||||
|
this.scale += other.scale - fracbits;
|
||||||
|
|
||||||
|
this.scaleUpTo(fracbits + 2);
|
||||||
|
this.internalRound(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param a a BigFloat
|
||||||
|
* @param b a BigFloat
|
||||||
|
* @return {@code a+b}
|
||||||
|
*/
|
||||||
|
public static BigFloat add(BigFloat a, BigFloat b) {
|
||||||
|
BigFloat c = a.copy();
|
||||||
|
c.add(b);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code this+=other}
|
||||||
|
*
|
||||||
|
* @param other a BigFloat
|
||||||
|
*/
|
||||||
|
public void add(BigFloat other) {
|
||||||
|
if (this.isNaN() || other.isNaN()) {
|
||||||
|
this.makeQuietNaN();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.isInfinite() && other.isInfinite()) {
|
||||||
|
if (this.sign != other.sign) {
|
||||||
|
this.makeQuietNaN();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.isInfinite()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (other.isInfinite()) {
|
||||||
|
copyFrom(other);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (other.isZero()) {
|
||||||
|
if (this.isZero()) {
|
||||||
|
this.sign = (this.sign < 0 && other.sign < 0) ? -1 : 1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.isZero()) {
|
||||||
|
copyFrom(other);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.sign == other.sign) {
|
||||||
|
add0(other);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sub0(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param a a BigFloat
|
||||||
|
* @param b a BigFloat
|
||||||
|
* @return {@code a-b}
|
||||||
|
*/
|
||||||
|
public static BigFloat sub(BigFloat a, BigFloat b) {
|
||||||
|
BigFloat c = b.copy();
|
||||||
|
c.sign *= -1;
|
||||||
|
c.add(a);
|
||||||
|
if (c.isZero()) {
|
||||||
|
c.sign = (a.sign < 0 && b.sign > 0) ? -1 : 1;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code this-=other}
|
||||||
|
*
|
||||||
|
* @param other a BigFloat
|
||||||
|
*/
|
||||||
|
public void sub(BigFloat other) {
|
||||||
|
int thissign = this.sign;
|
||||||
|
BigFloat nother = other.copy();
|
||||||
|
nother.sign *= -1;
|
||||||
|
this.add(nother);
|
||||||
|
if (this.isZero()) {
|
||||||
|
this.sign = (thissign < 0 && nother.sign < 0) ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// assume this and other are finite with the same sign, neither is zero
|
||||||
|
protected void add0(BigFloat other) {
|
||||||
|
int d = this.scale - other.scale;
|
||||||
|
|
||||||
|
if (d > fracbits + 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (d < -(fracbits + 1)) {
|
||||||
|
this.copyFrom(other);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean residue;
|
||||||
|
BigFloat a;
|
||||||
|
BigFloat b;
|
||||||
|
|
||||||
|
if (d >= 0) {
|
||||||
|
a = this;
|
||||||
|
b = other;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d = -d;
|
||||||
|
a = other;
|
||||||
|
b = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
residue = b.unscaled.getLowestSetBit() < d - 1;
|
||||||
|
this.scale = a.scale - 1;
|
||||||
|
this.unscaled = a.unscaled.shiftLeft(1).add(b.unscaled.shiftRight(d - 1));
|
||||||
|
|
||||||
|
scaleUpTo(fracbits + 2);
|
||||||
|
internalRound(residue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// assume this and other are finite with the opposite sign, neither is zero
|
||||||
|
protected void sub0(BigFloat other) {
|
||||||
|
int d = this.scale - other.scale;
|
||||||
|
|
||||||
|
if (d > fracbits + 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (d < -(fracbits + 2)) {
|
||||||
|
this.copyFrom(other);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean residue;
|
||||||
|
BigFloat a;
|
||||||
|
BigFloat b;
|
||||||
|
if (d >= 0) {
|
||||||
|
a = this;
|
||||||
|
b = other;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d = -d;
|
||||||
|
a = other;
|
||||||
|
b = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// d <= 0 is ok.. no residue and right shift will become left shift
|
||||||
|
residue = b.unscaled.getLowestSetBit() < d - 2;
|
||||||
|
this.sign = a.sign;
|
||||||
|
this.scale = a.scale - 2;
|
||||||
|
BigInteger x = b.unscaled;
|
||||||
|
x = x.shiftRight(d - 2);
|
||||||
|
if (residue) {
|
||||||
|
x = x.add(BigInteger.ONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.unscaled = a.unscaled.shiftLeft(2).subtract(x);
|
||||||
|
if (this.unscaled.signum() == 0) {
|
||||||
|
this.sign = 1; // cancellation results in positive 0.
|
||||||
|
}
|
||||||
|
else if (this.unscaled.signum() < 0) {
|
||||||
|
this.sign *= -1;
|
||||||
|
this.unscaled = this.unscaled.negate();
|
||||||
|
}
|
||||||
|
scaleUpTo(fracbits + 2);
|
||||||
|
internalRound(residue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param a a BigFloat
|
||||||
|
* @return the square root of {@code a}
|
||||||
|
*/
|
||||||
|
public static BigFloat sqrt(BigFloat a) {
|
||||||
|
BigFloat c = a.copy();
|
||||||
|
c.sqrt();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code this=sqrt(this)}
|
||||||
|
*
|
||||||
|
* <p>Square root by abacus algorithm, Martin Guy @ UKC, June 1985.
|
||||||
|
* From a book on programming abaci by Mr C. Woo.
|
||||||
|
* Argument is a positive integer, as is result.
|
||||||
|
*
|
||||||
|
* <p>adapted from http://medialab.freaknet.org/martin/src/sqrt/sqrt.c
|
||||||
|
*/
|
||||||
|
public void sqrt() {
|
||||||
|
if (this.isZero()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isNaN() || this.sign == -1) {
|
||||||
|
makeQuietNaN();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isInfinite()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BigInteger residue;
|
||||||
|
BigInteger result;
|
||||||
|
BigInteger bit;
|
||||||
|
|
||||||
|
//// force at least fracbits+2 bits of precision in the result
|
||||||
|
int sigbits = 2 * fracbits + 3;
|
||||||
|
this.scaleUpTo(sigbits);
|
||||||
|
|
||||||
|
// scale+fracbits needs to be even for the sqrt computation
|
||||||
|
if (((scale + fracbits) & 1) != 0) {
|
||||||
|
upscale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
residue = unscaled;
|
||||||
|
result = BigInteger.ZERO;
|
||||||
|
|
||||||
|
/* "bit" starts at the highest 4 power <= n. */
|
||||||
|
int pow = residue.bitLength() - 1; // highest 2 power <= n
|
||||||
|
pow -= pow & 1; // highest 4 power
|
||||||
|
bit = BigInteger.ONE.shiftLeft(pow);
|
||||||
|
|
||||||
|
while (bit.signum() != 0) {
|
||||||
|
BigInteger resp1 = result.add(bit);
|
||||||
|
if (residue.compareTo(resp1) >= 0) {
|
||||||
|
residue = residue.subtract(resp1);
|
||||||
|
result = result.add(bit.shiftLeft(1));
|
||||||
|
}
|
||||||
|
result = result.shiftRight(1);
|
||||||
|
bit = bit.shiftRight(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
unscaled = result;
|
||||||
|
scale = (scale + fracbits) / 2;
|
||||||
|
|
||||||
|
internalRound(residue.signum() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// floor, ignoring sign
|
||||||
|
private void floor0() {
|
||||||
|
// value = unscaled * 2^(scale-fracbits)
|
||||||
|
if (scale < 0) {
|
||||||
|
makeZero();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int nbitsUnderOne = fracbits - scale;
|
||||||
|
unscaled = unscaled.shiftRight(nbitsUnderOne).shiftLeft(nbitsUnderOne);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sign is not set
|
||||||
|
private void makeOne() {
|
||||||
|
kind = FloatKind.FINITE;
|
||||||
|
scale = 0;
|
||||||
|
unscaled = BigInteger.ONE.shiftLeft(fracbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ceil, ignoring sign
|
||||||
|
private void ceil0() {
|
||||||
|
if (isZero()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (scale < 0) {
|
||||||
|
makeOne();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nbitsUnderOne = fracbits - scale;
|
||||||
|
boolean increment = unscaled.getLowestSetBit() < nbitsUnderOne;
|
||||||
|
unscaled = unscaled.shiftRight(nbitsUnderOne).shiftLeft(nbitsUnderOne);
|
||||||
|
if (increment) {
|
||||||
|
unscaled = unscaled.add(BigInteger.ONE.shiftLeft(nbitsUnderOne));
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we carry to a new bit, change the scale
|
||||||
|
if (unscaled.bitLength() > fracbits + 1) {
|
||||||
|
upscale(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param a a BigFloat
|
||||||
|
* @return {@code floor(a)}
|
||||||
|
*/
|
||||||
|
public static BigFloat floor(BigFloat a) {
|
||||||
|
BigFloat b = a.copy();
|
||||||
|
b.floor();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code this=floor(this)}
|
||||||
|
*/
|
||||||
|
public void floor() {
|
||||||
|
switch (kind) {
|
||||||
|
case INFINITE:
|
||||||
|
return;
|
||||||
|
case SIGNALING_NAN:
|
||||||
|
makeQuietNaN();
|
||||||
|
case QUIET_NAN:
|
||||||
|
return;
|
||||||
|
case FINITE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sign >= 0) {
|
||||||
|
floor0();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ceil0();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param a a BigFloat
|
||||||
|
* @return {@code ceil(a)}
|
||||||
|
*/
|
||||||
|
public static BigFloat ceil(BigFloat a) {
|
||||||
|
BigFloat b = a.copy();
|
||||||
|
b.ceil();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code this=ceil(this)}
|
||||||
|
*/
|
||||||
|
public void ceil() {
|
||||||
|
switch (kind) {
|
||||||
|
case INFINITE:
|
||||||
|
return;
|
||||||
|
case SIGNALING_NAN:
|
||||||
|
makeQuietNaN();
|
||||||
|
case QUIET_NAN:
|
||||||
|
return;
|
||||||
|
case FINITE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sign >= 0) {
|
||||||
|
ceil0();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
floor0();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param a a BigFloat
|
||||||
|
* @return {@code trunc(a)} (round toward zero)
|
||||||
|
*/
|
||||||
|
public static BigFloat trunc(BigFloat a) {
|
||||||
|
BigFloat b = a.copy();
|
||||||
|
b.trunc();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code this=trunc(this)} (round toward zero)
|
||||||
|
*/
|
||||||
|
public void trunc() {
|
||||||
|
floor0();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code this*=-1}
|
||||||
|
*/
|
||||||
|
public void negate() {
|
||||||
|
this.sign *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param a a BigFloat
|
||||||
|
* @return {@code -a}
|
||||||
|
*/
|
||||||
|
public static BigFloat negate(BigFloat a) {
|
||||||
|
BigFloat b = a.copy();
|
||||||
|
b.negate();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param a a BigFloat
|
||||||
|
* @return {@code abs(a)}
|
||||||
|
*/
|
||||||
|
public static BigFloat abs(BigFloat a) {
|
||||||
|
BigFloat b = a.copy();
|
||||||
|
b.abs();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code this=abs(this)}
|
||||||
|
*/
|
||||||
|
public void abs() {
|
||||||
|
this.sign = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the truncated integer form of this BigFloat
|
||||||
|
*/
|
||||||
|
public BigInteger toBigInteger() {
|
||||||
|
BigInteger res = unscaled.shiftRight(fracbits - scale);
|
||||||
|
if (sign < 0) {
|
||||||
|
return res.negate();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param a a BigFloat
|
||||||
|
* @return {@code round(a)}
|
||||||
|
*/
|
||||||
|
public static BigFloat round(BigFloat a) {
|
||||||
|
BigFloat b = a.copy();
|
||||||
|
b.round();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code this=round(this)}
|
||||||
|
*/
|
||||||
|
public void round() {
|
||||||
|
BigFloat half = new BigFloat(fracbits, expbits, FloatKind.FINITE, +1,
|
||||||
|
BigInteger.ONE.shiftLeft(fracbits), -1);
|
||||||
|
add(half);
|
||||||
|
floor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(BigFloat other) {
|
||||||
|
// this == NaN
|
||||||
|
if (isNaN()) {
|
||||||
|
if (other.isNaN()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// this != NaN
|
||||||
|
if (other.isNaN()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (isInfinite()) {
|
||||||
|
// this == -inf
|
||||||
|
if (sign < 0) {
|
||||||
|
if (other.isInfinite() && other.sign < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// this == +inf
|
||||||
|
if (other.isInfinite() && other.sign > 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// this is finite
|
||||||
|
if (other.isInfinite()) {
|
||||||
|
return -other.sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
// other is finite
|
||||||
|
if (this.sign != other.sign) {
|
||||||
|
return this.sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
// both finite, same sign
|
||||||
|
int c = Integer.compare(this.scale, other.scale);
|
||||||
|
if (c != 0) {
|
||||||
|
return c * this.sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.sign * this.unscaled.compareTo(other.unscaled);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,11 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.floatformat;
|
package ghidra.pcode.floatformat;
|
||||||
|
|
||||||
|
enum FloatKind {
|
||||||
public enum Floatclass {
|
FINITE, /* includes both normal and subnormal */
|
||||||
normalized,
|
INFINITE,
|
||||||
infinity,
|
QUIET_NAN,
|
||||||
zero,
|
SIGNALING_NAN;
|
||||||
nan,
|
|
||||||
denormalized;
|
|
||||||
}
|
}
|
|
@ -85,8 +85,7 @@ public abstract class AbstractFloatDataType extends BuiltIn {
|
||||||
return doubleValue;
|
return doubleValue;
|
||||||
}
|
}
|
||||||
BigInteger value = Utils.bytesToBigInteger(bytes, len, buf.isBigEndian(), false);
|
BigInteger value = Utils.bytesToBigInteger(bytes, len, buf.isBigEndian(), false);
|
||||||
BigDecimal decValue = floatFormat.getHostFloat(value);
|
BigDecimal decValue = floatFormat.round(floatFormat.getHostFloat(value));
|
||||||
// TODO: adjust scale for improved display value ??
|
|
||||||
return decValue;
|
return decValue;
|
||||||
}
|
}
|
||||||
catch (UnsupportedFloatFormatException e) {
|
catch (UnsupportedFloatFormatException e) {
|
||||||
|
@ -197,7 +196,8 @@ public abstract class AbstractFloatDataType extends BuiltIn {
|
||||||
}
|
}
|
||||||
for (int size : floatMap.keySet()) {
|
for (int size : floatMap.keySet()) {
|
||||||
if (!newFloatMap.containsKey(size)) {
|
if (!newFloatMap.containsKey(size)) {
|
||||||
newFloatMap.put(size, (AbstractFloatDataType) floatMap.get(size).clone(dtm));
|
newFloatMap.put(size,
|
||||||
|
(AbstractFloatDataType) floatMap.get(size).clone(dtm));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,361 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.pcode.floatformat;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import generic.test.AbstractGenericTest;
|
||||||
|
|
||||||
|
public class BigFloatTest extends AbstractGenericTest {
|
||||||
|
public BigFloatTest() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIEEEFloatRepresentation() {
|
||||||
|
Assert.assertEquals("0b0.0", FloatFormat.toBinaryString(0.0f));
|
||||||
|
Assert.assertEquals("0b1.0 * 2^0", FloatFormat.toBinaryString(1.0f));
|
||||||
|
Assert.assertEquals("0b1.0 * 2^1", FloatFormat.toBinaryString(2.0f));
|
||||||
|
Assert.assertEquals("0b1.0 * 2^-1", FloatFormat.toBinaryString(0.5f));
|
||||||
|
Assert.assertEquals("-0b1.0 * 2^1", FloatFormat.toBinaryString(-2.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIEEEFloatAsBigFloat() {
|
||||||
|
Assert.assertEquals(FloatFormat.toBigFloat(0.0f).toBinaryString(),
|
||||||
|
FloatFormat.toBinaryString(0.0f));
|
||||||
|
Assert.assertEquals(FloatFormat.toBigFloat(1.0f).toBinaryString(),
|
||||||
|
FloatFormat.toBinaryString(1.0f));
|
||||||
|
Assert.assertEquals(FloatFormat.toBigFloat(2.0f).toBinaryString(),
|
||||||
|
FloatFormat.toBinaryString(2.0f));
|
||||||
|
Assert.assertEquals(FloatFormat.toBigFloat(0.5f).toBinaryString(),
|
||||||
|
FloatFormat.toBinaryString(0.5f));
|
||||||
|
Assert.assertEquals(FloatFormat.toBigFloat(-2.0f).toBinaryString(),
|
||||||
|
FloatFormat.toBinaryString(-2.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIEEEFloatAsBigFloatRandom() {
|
||||||
|
Random rand = new Random(1);
|
||||||
|
for (int i = 0; i < 100; ++i) {
|
||||||
|
float f = Float.intBitsToFloat(rand.nextInt());
|
||||||
|
Assert.assertEquals(FloatFormat.toBigFloat(f).toBinaryString(),
|
||||||
|
FloatFormat.toBinaryString(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIEEEDoubleRepresentation() {
|
||||||
|
Assert.assertEquals("0b0.0", FloatFormat.toBinaryString(0.0));
|
||||||
|
Assert.assertEquals("0b1.0 * 2^0", FloatFormat.toBinaryString(1.0));
|
||||||
|
Assert.assertEquals("0b1.0 * 2^1", FloatFormat.toBinaryString(2.0));
|
||||||
|
Assert.assertEquals("0b1.0 * 2^-1", FloatFormat.toBinaryString(0.5));
|
||||||
|
Assert.assertEquals("-0b1.0 * 2^1", FloatFormat.toBinaryString(-2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIEEEDoubleAsBigFloat() {
|
||||||
|
Assert.assertEquals(FloatFormat.toBigFloat(0.0).toBinaryString(),
|
||||||
|
FloatFormat.toBinaryString(0.0));
|
||||||
|
Assert.assertEquals(FloatFormat.toBigFloat(1.0).toBinaryString(),
|
||||||
|
FloatFormat.toBinaryString(1.0));
|
||||||
|
Assert.assertEquals(FloatFormat.toBigFloat(2.0).toBinaryString(),
|
||||||
|
FloatFormat.toBinaryString(2.0));
|
||||||
|
Assert.assertEquals(FloatFormat.toBigFloat(0.5).toBinaryString(),
|
||||||
|
FloatFormat.toBinaryString(0.5));
|
||||||
|
Assert.assertEquals(FloatFormat.toBigFloat(-2.0).toBinaryString(),
|
||||||
|
FloatFormat.toBinaryString(-2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIEEEDoubleAsBigFloatRandom() {
|
||||||
|
Random rand = new Random(1);
|
||||||
|
for (int i = 0; i < 100; ++i) {
|
||||||
|
double d = Double.longBitsToDouble(rand.nextLong());
|
||||||
|
Assert.assertEquals(FloatFormat.toBigFloat(d).toBinaryString(),
|
||||||
|
FloatFormat.toBinaryString(d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UnaryProc<T> {
|
||||||
|
void apply(T a);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UnaryOp<T> {
|
||||||
|
T apply(T a);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BinaryProc<T> {
|
||||||
|
void apply(T a, T b);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BinaryOp<T> {
|
||||||
|
T apply(T a, T b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// used for testing one-argument operations
|
||||||
|
final static int NUM_RANDOM_TEST_VALUES_UNARY = 1000;
|
||||||
|
// used for each operand of two-argument operations
|
||||||
|
final static int NUM_RANDOM_TEST_VALUES_BINARY = 100;
|
||||||
|
|
||||||
|
final static List<Float> testFloatList;
|
||||||
|
final static List<Float> testFloatShortList;
|
||||||
|
static {
|
||||||
|
Random rand = new Random(1);
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
List<Float> specialValues =
|
||||||
|
List.of(
|
||||||
|
-0.0f, 0.0f,
|
||||||
|
-1.0f, 1.0f,
|
||||||
|
-Float.MIN_VALUE, Float.MIN_VALUE,
|
||||||
|
-Float.MAX_VALUE, Float.MAX_VALUE,
|
||||||
|
-Float.MIN_NORMAL - Float.MIN_VALUE, -Float.MIN_NORMAL, -Float.MIN_NORMAL + Float.MIN_VALUE,
|
||||||
|
Float.MIN_NORMAL - Float.MIN_VALUE, Float.MIN_NORMAL, Float.MIN_NORMAL + Float.MIN_VALUE,
|
||||||
|
Float.NaN,
|
||||||
|
Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
|
||||||
|
// @formatter:on
|
||||||
|
Stream<Float> randStream = Stream.generate(rand::nextInt)
|
||||||
|
.limit(NUM_RANDOM_TEST_VALUES_UNARY)
|
||||||
|
.map(Float::intBitsToFloat);
|
||||||
|
|
||||||
|
testFloatList = Stream.concat(specialValues.stream(), randStream)
|
||||||
|
.collect(Collectors.toUnmodifiableList());
|
||||||
|
testFloatShortList =
|
||||||
|
testFloatList.subList(0, specialValues.size() + NUM_RANDOM_TEST_VALUES_BINARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
final static List<Double> testDoubleList;
|
||||||
|
final static List<Double> testDoubleShortList;
|
||||||
|
static {
|
||||||
|
Random rand = new Random(1);
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
List<Double> specialValues =
|
||||||
|
List.of(
|
||||||
|
-0.0, 0.0,
|
||||||
|
-1.0, 1.0,
|
||||||
|
-Double.MIN_VALUE, Double.MIN_VALUE,
|
||||||
|
-Double.MAX_VALUE, Double.MAX_VALUE,
|
||||||
|
-Double.MIN_NORMAL - Double.MIN_VALUE, -Double.MIN_NORMAL, -Double.MIN_NORMAL + Double.MIN_VALUE,
|
||||||
|
Double.MIN_NORMAL - Double.MIN_VALUE, Double.MIN_NORMAL, Double.MIN_NORMAL + Double.MIN_VALUE,
|
||||||
|
Double.NaN,
|
||||||
|
Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
Stream<Double> randStream = Stream.generate(rand::nextLong)
|
||||||
|
.limit(NUM_RANDOM_TEST_VALUES_UNARY)
|
||||||
|
.map(Double::longBitsToDouble);
|
||||||
|
|
||||||
|
testDoubleList = Stream.concat(specialValues.stream(), randStream)
|
||||||
|
.collect(Collectors.toUnmodifiableList());
|
||||||
|
testDoubleShortList =
|
||||||
|
testDoubleList.subList(0, specialValues.size() + NUM_RANDOM_TEST_VALUES_BINARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unaryDoubleOpTest(UnaryOp<Double> op, UnaryProc<BigFloat> bproc) {
|
||||||
|
int i = 0;
|
||||||
|
for (double fa : testDoubleList) {
|
||||||
|
BigFloat bfa = FloatFormat.toBigFloat(fa);
|
||||||
|
|
||||||
|
double fb = op.apply(fa);
|
||||||
|
bproc.apply(bfa);
|
||||||
|
|
||||||
|
assertEquals("case #" + Integer.toString(i), Double.isNaN(fb), bfa.isNaN());
|
||||||
|
if (!Double.isNaN(fb)) {
|
||||||
|
assertEquals("case #" + Integer.toString(i),
|
||||||
|
FloatFormat.toBinaryString(op.apply(fa)), bfa.toBinaryString());
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void binaryDoubleOpTest(BinaryOp<Double> op, BinaryProc<BigFloat> bproc) {
|
||||||
|
int i = 0;
|
||||||
|
for (double fa : testDoubleShortList) {
|
||||||
|
int j = 0;
|
||||||
|
for (double fb : testDoubleShortList) {
|
||||||
|
BigFloat bfa = FloatFormat.toBigFloat(fa);
|
||||||
|
BigFloat bfb = FloatFormat.toBigFloat(fb);
|
||||||
|
|
||||||
|
double fc = op.apply(fa, fb);
|
||||||
|
bproc.apply(bfa, bfb);
|
||||||
|
|
||||||
|
assertEquals(String.format("case #%d,%d", i, j), Double.isNaN(fc), bfa.isNaN());
|
||||||
|
if (!Double.isNaN(fc)) {
|
||||||
|
assertEquals(String.format("case #%d,%d", i, j), FloatFormat.toBinaryString(fc),
|
||||||
|
bfa.toBinaryString());
|
||||||
|
}
|
||||||
|
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unaryFloatOpTest(UnaryOp<Float> op, UnaryProc<BigFloat> bproc) {
|
||||||
|
int i = 0;
|
||||||
|
for (float fa : testFloatList) {
|
||||||
|
BigFloat bfa = FloatFormat.toBigFloat(fa);
|
||||||
|
|
||||||
|
float fb = op.apply(fa);
|
||||||
|
bproc.apply(bfa);
|
||||||
|
assertEquals("case #" + Integer.toString(i), Float.isNaN(fb), bfa.isNaN());
|
||||||
|
if (!Float.isNaN(fb)) {
|
||||||
|
assertEquals("case #" + Integer.toString(i), FloatFormat.toBinaryString(fb),
|
||||||
|
bfa.toBinaryString());
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void binaryFloatOpTest(BinaryOp<Float> op, BinaryProc<BigFloat> bproc) {
|
||||||
|
int i = 0;
|
||||||
|
for (float fa : testFloatShortList) {
|
||||||
|
int j = 0;
|
||||||
|
for (float fb : testFloatShortList) {
|
||||||
|
BigFloat bfa = FloatFormat.toBigFloat(fa);
|
||||||
|
BigFloat bfb = FloatFormat.toBigFloat(fb);
|
||||||
|
|
||||||
|
float fc = op.apply(fa, fb);
|
||||||
|
bproc.apply(bfa, bfb);
|
||||||
|
|
||||||
|
assertEquals(String.format("case #%d,%d", i, j), Float.isNaN(fc), bfa.isNaN());
|
||||||
|
if (!Float.isNaN(fc)) {
|
||||||
|
assertEquals(String.format("case #%d,%d", i, j), FloatFormat.toBinaryString(fc),
|
||||||
|
bfa.toBinaryString());
|
||||||
|
}
|
||||||
|
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFloatAdd() {
|
||||||
|
binaryFloatOpTest((a, b) -> a + b, (a, b) -> a.add(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFloatSubstract() {
|
||||||
|
binaryFloatOpTest((a, b) -> a - b, (a, b) -> a.sub(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFloatMultiply() {
|
||||||
|
binaryFloatOpTest((a, b) -> a * b, (a, b) -> a.mul(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFloatDivide() {
|
||||||
|
binaryFloatOpTest((a, b) -> a / b, (a, b) -> a.div(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFloatCompare() {
|
||||||
|
int i = 0;
|
||||||
|
for (float a : testFloatShortList) {
|
||||||
|
int j = 0;
|
||||||
|
BigFloat fa = FloatFormat.toBigFloat(a);
|
||||||
|
for (float b : testFloatShortList) {
|
||||||
|
BigFloat fb = FloatFormat.toBigFloat(b);
|
||||||
|
assertEquals(String.format("case #%d,%d", i, j), Float.compare(a, b),
|
||||||
|
fa.compareTo(fb));
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFloatSqrt() {
|
||||||
|
unaryFloatOpTest(a -> (float) Math.sqrt(a), a -> a.sqrt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFloatFloor() {
|
||||||
|
unaryFloatOpTest(a -> (float) Math.floor(a), a -> a.floor());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFloatCeil() {
|
||||||
|
unaryFloatOpTest(a -> (float) Math.ceil(a), a -> a.ceil());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleAdd() {
|
||||||
|
binaryDoubleOpTest((a, b) -> a + b, (a, b) -> a.add(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleSubstract() {
|
||||||
|
binaryDoubleOpTest((a, b) -> a - b, (a, b) -> a.sub(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleMultiply() {
|
||||||
|
binaryDoubleOpTest((a, b) -> a * b, (a, b) -> a.mul(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleDivide() {
|
||||||
|
binaryDoubleOpTest((a, b) -> a / b, (a, b) -> a.div(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleCompare() {
|
||||||
|
int i = 0;
|
||||||
|
for (double a : testDoubleShortList) {
|
||||||
|
int j = 0;
|
||||||
|
BigFloat fa = FloatFormat.toBigFloat(a);
|
||||||
|
for (double b : testDoubleShortList) {
|
||||||
|
BigFloat fb = FloatFormat.toBigFloat(b);
|
||||||
|
assertEquals(String.format("case #%d,%d", i, j), Double.compare(a, b),
|
||||||
|
fa.compareTo(fb));
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleSqrt() {
|
||||||
|
unaryDoubleOpTest(a -> Math.sqrt(a), a -> a.sqrt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleFloor() {
|
||||||
|
unaryDoubleOpTest(a -> Math.floor(a), a -> a.floor());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleCeil() {
|
||||||
|
unaryDoubleOpTest(a -> Math.ceil(a), a -> a.ceil());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -65,25 +64,25 @@ public class OpBehaviorFloatAbsTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigInteger a = ff.getEncoding(BigDecimal.valueOf(2.5d));
|
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
|
||||||
BigInteger result = op.evaluateUnary(8, 8, a);
|
BigInteger result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(2.5d), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(2.5d), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(-2.5d));
|
a = ff.getEncoding(ff.getBigFloat(-2.5d));
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(2.5d), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(2.5d), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(false);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_POSITIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(true);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_POSITIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NaN);
|
a = ff.getBigNaNEncoding(false);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NaN, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -75,35 +74,35 @@ public class OpBehaviorFloatAddTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigInteger a = ff.getEncoding(BigDecimal.valueOf(1.234d));
|
BigInteger a = ff.getEncoding(ff.getBigFloat(1.234d));
|
||||||
BigInteger b = ff.getEncoding(BigDecimal.valueOf(1.123d));
|
BigInteger b = ff.getEncoding(ff.getBigFloat(1.123d));
|
||||||
BigInteger result = op.evaluateBinary(8, 8, a, b);// 1.234 + 1.123
|
BigInteger result = op.evaluateBinary(8, 8, a, b);// 1.234 + 1.123
|
||||||
Assert.assertEquals(BigDecimal.valueOf(2.357), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(2.357), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(-1.123d));
|
a = ff.getEncoding(ff.getBigFloat(-1.123d));
|
||||||
result = op.evaluateBinary(8, 8, a, b);// -1.123 + 1.123
|
result = op.evaluateBinary(8, 8, a, b);// -1.123 + 1.123
|
||||||
Assert.assertEquals(BigDecimal.ZERO, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigZero(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY);
|
a = ff.getEncoding(ff.getBigInfinity(false));
|
||||||
result = op.evaluateBinary(8, 8, a, b);// +INFINITY + 1.123
|
result = op.evaluateBinary(8, 8, a, b);// +INFINITY + 1.123
|
||||||
Assert.assertEquals(FloatFormat.BIG_POSITIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(true);
|
||||||
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + 1.123
|
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + 1.123
|
||||||
Assert.assertEquals(FloatFormat.BIG_NEGATIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
|
||||||
|
|
||||||
b = ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY);
|
b = ff.getBigInfinityEncoding(true);
|
||||||
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + -INFINITY
|
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + -INFINITY
|
||||||
Assert.assertEquals(FloatFormat.BIG_NEGATIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
|
||||||
|
|
||||||
b = ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY);
|
b = ff.getEncoding(ff.getBigInfinity(false));
|
||||||
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + +INFINITY
|
result = op.evaluateBinary(8, 8, a, b);// -INFINITY + +INFINITY
|
||||||
Assert.assertEquals(FloatFormat.BIG_NaN, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NaN);
|
a = ff.getBigNaNEncoding(false);
|
||||||
b = ff.getEncoding(BigDecimal.valueOf(1.123d));
|
b = ff.getEncoding(ff.getBigFloat(1.123d));
|
||||||
result = op.evaluateBinary(8, 8, a, b);// NaN + 1.123
|
result = op.evaluateBinary(8, 8, a, b);// NaN + 1.123
|
||||||
Assert.assertEquals(FloatFormat.BIG_NaN, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -65,26 +64,25 @@ public class OpBehaviorFloatCeilTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigInteger a = ff.getEncoding(BigDecimal.valueOf(2.5d));
|
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
|
||||||
BigInteger result = op.evaluateUnary(8, 8, a);
|
BigInteger result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(3.0d).stripTrailingZeros(), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(3.0d), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(-2.5d));
|
a = ff.getEncoding(ff.getBigFloat(-2.5d));
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(-2.0d).stripTrailingZeros(),
|
Assert.assertEquals(ff.getBigFloat(-2.0d), ff.getHostFloat(result));
|
||||||
ff.getHostFloat(result));
|
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(false);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_POSITIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(true);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NEGATIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NaN);
|
a = ff.getBigNaNEncoding(false);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NaN, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -62,22 +61,22 @@ public class OpBehaviorFloatDivTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigInteger a = ff.getEncoding(BigDecimal.valueOf(3.75d));
|
BigInteger a = ff.getEncoding(ff.getBigFloat(3.75d));
|
||||||
BigInteger b = ff.getEncoding(BigDecimal.valueOf(1.5d));
|
BigInteger b = ff.getEncoding(ff.getBigFloat(1.5d));
|
||||||
BigInteger result = op.evaluateBinary(8, 8, a, b);
|
BigInteger result = op.evaluateBinary(8, 8, a, b);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(2.5d), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(2.5d), ff.getHostFloat(result));
|
||||||
|
|
||||||
b = ff.getEncoding(BigDecimal.ZERO);
|
b = ff.getBigZeroEncoding(false);
|
||||||
result = op.evaluateBinary(8, 8, a, b);
|
result = op.evaluateBinary(8, 8, a, b);
|
||||||
Assert.assertEquals(FloatFormat.BIG_POSITIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(-3.75d));
|
a = ff.getEncoding(ff.getBigFloat(-3.75d));
|
||||||
result = op.evaluateBinary(8, 8, a, b);
|
result = op.evaluateBinary(8, 8, a, b);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NEGATIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
|
||||||
|
|
||||||
b = ff.getEncoding(FloatFormat.BIG_NaN);
|
b = ff.getBigNaNEncoding(false);
|
||||||
result = op.evaluateBinary(8, 8, a, b);
|
result = op.evaluateBinary(8, 8, a, b);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NaN, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ghidra.pcode.floatformat.FloatFormat;
|
import ghidra.pcode.floatformat.*;
|
||||||
import ghidra.pcode.floatformat.FloatFormatFactory;
|
|
||||||
|
|
||||||
public class OpBehaviorFloatEqualTest extends AbstractOpBehaviorTest {
|
public class OpBehaviorFloatEqualTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
|
@ -30,63 +28,53 @@ public class OpBehaviorFloatEqualTest extends AbstractOpBehaviorTest {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryLong() {
|
public void testEvaluateBinaryLong() {
|
||||||
|
|
||||||
OpBehaviorFloatEqual op = new OpBehaviorFloatEqual();
|
OpBehaviorFloatEqual op = new OpBehaviorFloatEqual();
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(1.234)));
|
Assert.assertEquals(1,
|
||||||
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(-1.234)));
|
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(1.234)));
|
||||||
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(1.234)));
|
Assert.assertEquals(1,
|
||||||
Assert.assertEquals(
|
op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(-1.234)));
|
||||||
1,
|
Assert.assertEquals(0,
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(1.234)));
|
||||||
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
||||||
Assert.assertEquals(
|
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
||||||
0,
|
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
ff.getEncoding(Double.NEGATIVE_INFINITY)));
|
||||||
ff.getEncoding(Double.NEGATIVE_INFINITY)));
|
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
|
||||||
Assert.assertEquals(
|
ff.getEncoding(Double.NEGATIVE_INFINITY)));
|
||||||
1,
|
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
|
ff.getEncoding(Double.NaN)));
|
||||||
ff.getEncoding(Double.NEGATIVE_INFINITY)));
|
|
||||||
Assert.assertEquals(
|
|
||||||
0,
|
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
|
||||||
ff.getEncoding(Double.NaN)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryBigInteger() {
|
public void testEvaluateBinaryBigInteger() {
|
||||||
|
|
||||||
OpBehaviorFloatEqual op = new OpBehaviorFloatEqual();
|
OpBehaviorFloatEqual op = new OpBehaviorFloatEqual();
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigDecimal a = BigDecimal.valueOf(1.234d);
|
BigFloat a = ff.getBigFloat(1.234d);
|
||||||
BigDecimal b = BigDecimal.valueOf(-1.234d);
|
BigFloat b = ff.getBigFloat(-1.234d);
|
||||||
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(a)));
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(b)));
|
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(a)));
|
||||||
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(a)));
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
Assert.assertEquals(
|
op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(b)));
|
||||||
BigInteger.ONE,
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY),
|
op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(a)));
|
||||||
ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY)));
|
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8,
|
||||||
Assert.assertEquals(
|
ff.getBigInfinityEncoding(false), ff.getBigInfinityEncoding(false)));
|
||||||
BigInteger.ZERO,
|
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(8, 8,
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY),
|
ff.getBigInfinityEncoding(false), ff.getBigInfinityEncoding(true)));
|
||||||
ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY)));
|
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(true),
|
||||||
Assert.assertEquals(
|
ff.getBigInfinityEncoding(true)));
|
||||||
BigInteger.ONE,
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY),
|
op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(false), ff.getBigNaNEncoding(false)));
|
||||||
ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY)));
|
|
||||||
Assert.assertEquals(
|
|
||||||
BigInteger.ZERO,
|
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY),
|
|
||||||
ff.getEncoding(FloatFormat.BIG_NaN)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -67,25 +66,25 @@ public class OpBehaviorFloatFloat2FloatTest extends AbstractOpBehaviorTest {
|
||||||
FloatFormat ff8 = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff8 = FloatFormatFactory.getFloatFormat(8);
|
||||||
FloatFormat ff4 = FloatFormatFactory.getFloatFormat(4);
|
FloatFormat ff4 = FloatFormatFactory.getFloatFormat(4);
|
||||||
|
|
||||||
BigInteger a = ff4.getEncoding(BigDecimal.valueOf(1.75d));
|
BigInteger a = ff4.getEncoding(ff4.getBigFloat(1.75d));
|
||||||
BigInteger result = op.evaluateUnary(8, 4, a);
|
BigInteger result = op.evaluateUnary(8, 4, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(1.75d), ff8.getHostFloat(result));
|
Assert.assertEquals(ff8.getBigFloat(1.75d), ff8.getHostFloat(result));
|
||||||
|
|
||||||
a = ff4.getEncoding(BigDecimal.valueOf(-1.75d));
|
a = ff4.getEncoding(ff4.getBigFloat(-1.75d));
|
||||||
result = op.evaluateUnary(8, 4, a);
|
result = op.evaluateUnary(8, 4, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(-1.75d), ff8.getHostFloat(result));
|
Assert.assertEquals(ff8.getBigFloat(-1.75d), ff8.getHostFloat(result));
|
||||||
|
|
||||||
a = ff4.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY);
|
a = ff4.getEncoding(ff4.getBigInfinity(false));
|
||||||
result = op.evaluateUnary(8, 4, a);
|
result = op.evaluateUnary(8, 4, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_POSITIVE_INFINITY, ff8.getHostFloat(result));
|
Assert.assertEquals(ff8.getBigInfinity(false), ff8.getHostFloat(result));
|
||||||
|
|
||||||
a = ff4.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY);
|
a = ff4.getEncoding(ff4.getBigInfinity(true));
|
||||||
result = op.evaluateUnary(8, 4, a);
|
result = op.evaluateUnary(8, 4, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NEGATIVE_INFINITY, ff8.getHostFloat(result));
|
Assert.assertEquals(ff8.getBigInfinity(true), ff8.getHostFloat(result));
|
||||||
|
|
||||||
a = ff4.getEncoding(FloatFormat.BIG_NaN);
|
a = ff4.getEncoding(ff4.getBigNaN(false));
|
||||||
result = op.evaluateUnary(8, 4, a);
|
result = op.evaluateUnary(8, 4, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NaN, ff8.getHostFloat(result));
|
Assert.assertEquals(ff8.getBigNaN(false), ff8.getHostFloat(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -69,31 +68,29 @@ public class OpBehaviorFloatFloorTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigInteger a = ff.getEncoding(BigDecimal.valueOf(2.5d));
|
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
|
||||||
BigInteger result = op.evaluateUnary(8, 8, a);
|
BigInteger result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(2.0d).stripTrailingZeros(), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(2.0d), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(-2.0d));
|
a = ff.getEncoding(ff.getBigFloat(-2.0d));
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(-2.0d).stripTrailingZeros(),
|
Assert.assertEquals(ff.getBigFloat(-2.0d), ff.getHostFloat(result));
|
||||||
ff.getHostFloat(result));
|
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(-2.5d));
|
a = ff.getEncoding(ff.getBigFloat(-2.5d));
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(-3.0d).stripTrailingZeros(),
|
Assert.assertEquals(ff.getBigFloat(-3.0d), ff.getHostFloat(result));
|
||||||
ff.getHostFloat(result));
|
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(false);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_POSITIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(true);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NEGATIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NaN);
|
a = ff.getBigNaNEncoding(false);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NaN, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -68,22 +67,20 @@ public class OpBehaviorFloatInt2FloatTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
BigInteger result = op.evaluateUnary(4, 4, BigInteger.valueOf(2));
|
BigInteger result = op.evaluateUnary(4, 4, BigInteger.valueOf(2));
|
||||||
assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used
|
assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used
|
||||||
Assert.assertEquals(BigDecimal.valueOf(2.0d).stripTrailingZeros(), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(2.0d), ff.getHostFloat(result));
|
||||||
|
|
||||||
result = op.evaluateUnary(4, 4, BigInteger.valueOf(-2));
|
result = op.evaluateUnary(4, 4, BigInteger.valueOf(-2));
|
||||||
assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used
|
assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used
|
||||||
Assert.assertEquals(BigDecimal.valueOf(-2.0d).stripTrailingZeros(),
|
Assert.assertEquals(ff.getBigFloat(-2.0d), ff.getHostFloat(result));
|
||||||
ff.getHostFloat(result));
|
|
||||||
|
|
||||||
result = op.evaluateUnary(4, 4, BigInteger.ZERO);
|
result = op.evaluateUnary(4, 4, BigInteger.ZERO);
|
||||||
assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used
|
assertTrue(result.compareTo(limit) < 0);// verify that only 4-bytes are used
|
||||||
Assert.assertEquals(BigDecimal.ZERO, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigZero(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
BigInteger NEG_ONE = Utils.bytesToBigInteger(
|
BigInteger NEG_ONE = Utils.bytesToBigInteger(
|
||||||
new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }, 4, false, false);
|
new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }, 4, false, false);
|
||||||
result = op.evaluateUnary(4, 4, NEG_ONE);
|
result = op.evaluateUnary(4, 4, NEG_ONE);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(-1.0d).stripTrailingZeros(),
|
Assert.assertEquals(ff.getBigFloat(-1.0d), ff.getHostFloat(result));
|
||||||
ff.getHostFloat(result));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,14 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ghidra.pcode.floatformat.FloatFormat;
|
import ghidra.pcode.floatformat.*;
|
||||||
import ghidra.pcode.floatformat.FloatFormatFactory;
|
|
||||||
|
|
||||||
public class OpBehaviorFloatLessEqualTest extends AbstractOpBehaviorTest {
|
public class OpBehaviorFloatLessEqualTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
|
@ -30,92 +28,80 @@ public class OpBehaviorFloatLessEqualTest extends AbstractOpBehaviorTest {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryLong() {
|
public void testEvaluateBinaryLong() {
|
||||||
|
|
||||||
OpBehaviorFloatLessEqual op = new OpBehaviorFloatLessEqual();
|
OpBehaviorFloatLessEqual op = new OpBehaviorFloatLessEqual();
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(1.234)));
|
Assert.assertEquals(1,
|
||||||
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(-1.234)));
|
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(1.234)));
|
||||||
|
Assert.assertEquals(1,
|
||||||
|
op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(-1.234)));
|
||||||
|
|
||||||
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(-1.234)));
|
Assert.assertEquals(0,
|
||||||
|
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(-1.234)));
|
||||||
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(0), ff.getEncoding(-1.234)));
|
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(0), ff.getEncoding(-1.234)));
|
||||||
|
|
||||||
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(0), ff.getEncoding(1.234)));
|
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(0), ff.getEncoding(1.234)));
|
||||||
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(1.234)));
|
Assert.assertEquals(1,
|
||||||
|
op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(1.234)));
|
||||||
|
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
||||||
0,
|
ff.getEncoding(1.234)));
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY), ff.getEncoding(1.234)));
|
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
|
||||||
Assert.assertEquals(
|
ff.getEncoding(1.234)));
|
||||||
1,
|
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(1.234),
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY), ff.getEncoding(1.234)));
|
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(1.234),
|
||||||
1,
|
ff.getEncoding(Double.NEGATIVE_INFINITY)));
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(Double.POSITIVE_INFINITY)));
|
|
||||||
Assert.assertEquals(
|
|
||||||
0,
|
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(Double.NEGATIVE_INFINITY)));
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
||||||
1,
|
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
|
||||||
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
||||||
Assert.assertEquals(
|
|
||||||
1,
|
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
|
|
||||||
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryBigInteger() {
|
public void testEvaluateBinaryBigInteger() {
|
||||||
|
|
||||||
OpBehaviorFloatLessEqual op = new OpBehaviorFloatLessEqual();
|
OpBehaviorFloatLessEqual op = new OpBehaviorFloatLessEqual();
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigDecimal a = BigDecimal.valueOf(1.234d);
|
BigFloat a = ff.getBigFloat(1.234d);
|
||||||
BigDecimal b = BigDecimal.valueOf(-1.234d);
|
BigFloat b = ff.getBigFloat(-1.234d);
|
||||||
|
|
||||||
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(a)));
|
|
||||||
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(b)));
|
|
||||||
|
|
||||||
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(b)));
|
|
||||||
Assert.assertEquals(BigInteger.ZERO,
|
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(BigDecimal.ZERO), ff.getEncoding(b)));
|
|
||||||
|
|
||||||
Assert.assertEquals(BigInteger.ONE,
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(BigDecimal.ZERO), ff.getEncoding(a)));
|
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(a)));
|
||||||
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(a)));
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
|
op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(b)));
|
||||||
|
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
BigInteger.ZERO,
|
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(b)));
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY),
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
ff.getEncoding(a)));
|
op.evaluateBinary(8, 8, ff.getBigZeroEncoding(false), ff.getEncoding(b)));
|
||||||
Assert.assertEquals(
|
|
||||||
BigInteger.ONE,
|
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY),
|
|
||||||
ff.getEncoding(a)));
|
|
||||||
Assert.assertEquals(
|
|
||||||
BigInteger.ONE,
|
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(a),
|
|
||||||
ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY)));
|
|
||||||
Assert.assertEquals(
|
|
||||||
BigInteger.ZERO,
|
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(a),
|
|
||||||
ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY)));
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
BigInteger.ONE,
|
op.evaluateBinary(8, 8, ff.getBigZeroEncoding(false), ff.getEncoding(a)));
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY),
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY)));
|
op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(a)));
|
||||||
Assert.assertEquals(
|
|
||||||
BigInteger.ONE,
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY),
|
op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(false), ff.getEncoding(a)));
|
||||||
ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY)));
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
|
op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(true), ff.getEncoding(a)));
|
||||||
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
|
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getBigInfinityEncoding(false)));
|
||||||
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
|
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getBigInfinityEncoding(true)));
|
||||||
|
|
||||||
|
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8,
|
||||||
|
ff.getBigInfinityEncoding(false), ff.getBigInfinityEncoding(false)));
|
||||||
|
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(true),
|
||||||
|
ff.getBigInfinityEncoding(false)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,14 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ghidra.pcode.floatformat.FloatFormat;
|
import ghidra.pcode.floatformat.*;
|
||||||
import ghidra.pcode.floatformat.FloatFormatFactory;
|
|
||||||
|
|
||||||
public class OpBehaviorFloatLessTest extends AbstractOpBehaviorTest {
|
public class OpBehaviorFloatLessTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
|
@ -30,89 +28,77 @@ public class OpBehaviorFloatLessTest extends AbstractOpBehaviorTest {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryLong() {
|
public void testEvaluateBinaryLong() {
|
||||||
|
|
||||||
OpBehaviorFloatLess op = new OpBehaviorFloatLess();
|
OpBehaviorFloatLess op = new OpBehaviorFloatLess();
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(1.234)));
|
Assert.assertEquals(0,
|
||||||
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(-1.234)));
|
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(1.234)));
|
||||||
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(-1.234)));
|
Assert.assertEquals(0,
|
||||||
|
op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(-1.234)));
|
||||||
|
Assert.assertEquals(0,
|
||||||
|
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(-1.234)));
|
||||||
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(0), ff.getEncoding(-1.234)));
|
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(0), ff.getEncoding(-1.234)));
|
||||||
|
|
||||||
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(0), ff.getEncoding(1.234)));
|
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(0), ff.getEncoding(1.234)));
|
||||||
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(1.234)));
|
Assert.assertEquals(1,
|
||||||
|
op.evaluateBinary(8, 8, ff.getEncoding(-1.234), ff.getEncoding(1.234)));
|
||||||
|
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
||||||
0,
|
ff.getEncoding(1.234)));
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY), ff.getEncoding(1.234)));
|
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
|
||||||
Assert.assertEquals(
|
ff.getEncoding(1.234)));
|
||||||
1,
|
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(1.234),
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY), ff.getEncoding(1.234)));
|
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(1.234),
|
||||||
1,
|
ff.getEncoding(Double.NEGATIVE_INFINITY)));
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(Double.POSITIVE_INFINITY)));
|
|
||||||
Assert.assertEquals(
|
|
||||||
0,
|
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(1.234), ff.getEncoding(Double.NEGATIVE_INFINITY)));
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(0, op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
||||||
0,
|
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
Assert.assertEquals(1, op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
|
||||||
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
||||||
Assert.assertEquals(
|
|
||||||
1,
|
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
|
|
||||||
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryBigInteger() {
|
public void testEvaluateBinaryBigInteger() {
|
||||||
|
|
||||||
OpBehaviorFloatLess op = new OpBehaviorFloatLess();
|
OpBehaviorFloatLess op = new OpBehaviorFloatLess();
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigDecimal a = BigDecimal.valueOf(1.234d);
|
BigFloat a = ff.getBigFloat(1.234d);
|
||||||
BigDecimal b = BigDecimal.valueOf(-1.234d);
|
BigFloat b = ff.getBigFloat(-1.234d);
|
||||||
|
|
||||||
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(a)));
|
|
||||||
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(b)));
|
|
||||||
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(b)));
|
|
||||||
Assert.assertEquals(BigInteger.ZERO,
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(BigDecimal.ZERO), ff.getEncoding(b)));
|
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(a)));
|
||||||
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
|
op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(b)));
|
||||||
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
|
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getEncoding(b)));
|
||||||
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
|
op.evaluateBinary(8, 8, ff.getBigZeroEncoding(false), ff.getEncoding(b)));
|
||||||
|
|
||||||
Assert.assertEquals(BigInteger.ONE,
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(BigDecimal.ZERO), ff.getEncoding(a)));
|
op.evaluateBinary(8, 8, ff.getBigZeroEncoding(false), ff.getEncoding(a)));
|
||||||
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(a)));
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
|
op.evaluateBinary(8, 8, ff.getEncoding(b), ff.getEncoding(a)));
|
||||||
|
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
BigInteger.ZERO,
|
op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(false), ff.getEncoding(a)));
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY),
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
ff.getEncoding(a)));
|
op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(true), ff.getEncoding(a)));
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
BigInteger.ONE,
|
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getBigInfinityEncoding(false)));
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY),
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
ff.getEncoding(a)));
|
op.evaluateBinary(8, 8, ff.getEncoding(a), ff.getBigInfinityEncoding(true)));
|
||||||
Assert.assertEquals(
|
|
||||||
BigInteger.ONE,
|
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(a),
|
|
||||||
ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY)));
|
|
||||||
Assert.assertEquals(
|
|
||||||
BigInteger.ZERO,
|
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(a),
|
|
||||||
ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY)));
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(8, 8,
|
||||||
BigInteger.ZERO,
|
ff.getBigInfinityEncoding(false), ff.getBigInfinityEncoding(false)));
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY),
|
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(8, 8, ff.getBigInfinityEncoding(true),
|
||||||
ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY)));
|
ff.getBigInfinityEncoding(false)));
|
||||||
Assert.assertEquals(
|
|
||||||
BigInteger.ONE,
|
|
||||||
op.evaluateBinary(8, 8, ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY),
|
|
||||||
ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -62,22 +61,22 @@ public class OpBehaviorFloatMultTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigInteger a = ff.getEncoding(BigDecimal.valueOf(2.5d));
|
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
|
||||||
BigInteger b = ff.getEncoding(BigDecimal.valueOf(1.5d));
|
BigInteger b = ff.getEncoding(ff.getBigFloat(1.5d));
|
||||||
BigInteger result = op.evaluateBinary(8, 8, a, b);
|
BigInteger result = op.evaluateBinary(8, 8, a, b);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(3.75d), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(3.75d), ff.getHostFloat(result));
|
||||||
|
|
||||||
b = ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY);
|
b = ff.getBigInfinityEncoding(false);
|
||||||
result = op.evaluateBinary(8, 8, a, b);
|
result = op.evaluateBinary(8, 8, a, b);
|
||||||
Assert.assertEquals(FloatFormat.BIG_POSITIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(true);
|
||||||
result = op.evaluateBinary(8, 8, a, b);
|
result = op.evaluateBinary(8, 8, a, b);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NEGATIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
|
||||||
|
|
||||||
b = ff.getEncoding(FloatFormat.BIG_NaN);
|
b = ff.getBigNaNEncoding(false);
|
||||||
result = op.evaluateBinary(8, 8, a, b);
|
result = op.evaluateBinary(8, 8, a, b);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NaN, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -30,8 +29,8 @@ public class OpBehaviorFloatNanTest extends AbstractOpBehaviorTest {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryLong() {
|
public void testEvaluateBinaryLong() {
|
||||||
|
|
||||||
OpBehaviorFloatNan op = new OpBehaviorFloatNan();
|
OpBehaviorFloatNan op = new OpBehaviorFloatNan();
|
||||||
|
|
||||||
|
@ -42,17 +41,17 @@ public class OpBehaviorFloatNanTest extends AbstractOpBehaviorTest {
|
||||||
Assert.assertEquals(0, op.evaluateUnary(1, 8, ff.getEncoding(1.234)));
|
Assert.assertEquals(0, op.evaluateUnary(1, 8, ff.getEncoding(1.234)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryBigInteger() {
|
public void testEvaluateBinaryBigInteger() {
|
||||||
|
|
||||||
OpBehaviorFloatNan op = new OpBehaviorFloatNan();
|
OpBehaviorFloatNan op = new OpBehaviorFloatNan();
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
Assert.assertEquals(BigInteger.ONE, op.evaluateUnary(1, 8, ff.getEncoding(FloatFormat.BIG_NaN)));
|
Assert.assertEquals(BigInteger.ONE, op.evaluateUnary(1, 8, ff.getBigNaNEncoding(false)));
|
||||||
Assert.assertEquals(BigInteger.ZERO, op.evaluateUnary(1, 8, ff.getEncoding(BigDecimal.ZERO)));
|
Assert.assertEquals(BigInteger.ZERO, op.evaluateUnary(1, 8, ff.getBigZeroEncoding(false)));
|
||||||
Assert.assertEquals(BigInteger.ZERO,
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
op.evaluateUnary(1, 8, ff.getEncoding(BigDecimal.valueOf(1.234d))));
|
op.evaluateUnary(1, 8, ff.getEncoding(ff.getBigFloat(1.234d))));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -65,25 +64,25 @@ public class OpBehaviorFloatNegTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigInteger a = ff.getEncoding(BigDecimal.valueOf(2.5d));
|
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
|
||||||
BigInteger result = op.evaluateUnary(8, 8, a);
|
BigInteger result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(-2.5d), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(-2.5d), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(-2.5d));
|
a = ff.getEncoding(ff.getBigFloat(-2.5d));
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(2.5d), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(2.5d), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(false);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NEGATIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(true);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_POSITIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NaN);
|
a = ff.getBigNaNEncoding(false);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NaN, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ghidra.pcode.floatformat.FloatFormat;
|
import ghidra.pcode.floatformat.*;
|
||||||
import ghidra.pcode.floatformat.FloatFormatFactory;
|
|
||||||
|
|
||||||
public class OpBehaviorFloatNotEqualTest extends AbstractOpBehaviorTest {
|
public class OpBehaviorFloatNotEqualTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
|
@ -30,63 +28,53 @@ public class OpBehaviorFloatNotEqualTest extends AbstractOpBehaviorTest {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryLong() {
|
public void testEvaluateBinaryLong() {
|
||||||
|
|
||||||
OpBehaviorFloatNotEqual op = new OpBehaviorFloatNotEqual();
|
OpBehaviorFloatNotEqual op = new OpBehaviorFloatNotEqual();
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
Assert.assertEquals(0, op.evaluateBinary(1, 8, ff.getEncoding(1.234), ff.getEncoding(1.234)));
|
Assert.assertEquals(0,
|
||||||
Assert.assertEquals(0, op.evaluateBinary(1, 8, ff.getEncoding(-1.234), ff.getEncoding(-1.234)));
|
op.evaluateBinary(1, 8, ff.getEncoding(1.234), ff.getEncoding(1.234)));
|
||||||
Assert.assertEquals(1, op.evaluateBinary(1, 8, ff.getEncoding(-1.234), ff.getEncoding(1.234)));
|
Assert.assertEquals(0,
|
||||||
Assert.assertEquals(
|
op.evaluateBinary(1, 8, ff.getEncoding(-1.234), ff.getEncoding(-1.234)));
|
||||||
0,
|
Assert.assertEquals(1,
|
||||||
op.evaluateBinary(1, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
op.evaluateBinary(1, 8, ff.getEncoding(-1.234), ff.getEncoding(1.234)));
|
||||||
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
Assert.assertEquals(0, op.evaluateBinary(1, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
||||||
Assert.assertEquals(
|
ff.getEncoding(Double.POSITIVE_INFINITY)));
|
||||||
1,
|
Assert.assertEquals(1, op.evaluateBinary(1, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
||||||
op.evaluateBinary(1, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
ff.getEncoding(Double.NEGATIVE_INFINITY)));
|
||||||
ff.getEncoding(Double.NEGATIVE_INFINITY)));
|
Assert.assertEquals(0, op.evaluateBinary(1, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
|
||||||
Assert.assertEquals(
|
ff.getEncoding(Double.NEGATIVE_INFINITY)));
|
||||||
0,
|
Assert.assertEquals(1, op.evaluateBinary(1, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
||||||
op.evaluateBinary(1, 8, ff.getEncoding(Double.NEGATIVE_INFINITY),
|
ff.getEncoding(Double.NaN)));
|
||||||
ff.getEncoding(Double.NEGATIVE_INFINITY)));
|
|
||||||
Assert.assertEquals(
|
|
||||||
1,
|
|
||||||
op.evaluateBinary(1, 8, ff.getEncoding(Double.POSITIVE_INFINITY),
|
|
||||||
ff.getEncoding(Double.NaN)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryBigInteger() {
|
public void testEvaluateBinaryBigInteger() {
|
||||||
|
|
||||||
OpBehaviorFloatNotEqual op = new OpBehaviorFloatNotEqual();
|
OpBehaviorFloatNotEqual op = new OpBehaviorFloatNotEqual();
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigDecimal a = BigDecimal.valueOf(1.234d);
|
BigFloat a = ff.getBigFloat(1.234d);
|
||||||
BigDecimal b = BigDecimal.valueOf(-1.234d);
|
BigFloat b = ff.getBigFloat(-1.234d);
|
||||||
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(1, 8, ff.getEncoding(a), ff.getEncoding(a)));
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(1, 8, ff.getEncoding(b), ff.getEncoding(b)));
|
op.evaluateBinary(1, 8, ff.getEncoding(a), ff.getEncoding(a)));
|
||||||
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(1, 8, ff.getEncoding(b), ff.getEncoding(a)));
|
Assert.assertEquals(BigInteger.ZERO,
|
||||||
Assert.assertEquals(
|
op.evaluateBinary(1, 8, ff.getEncoding(b), ff.getEncoding(b)));
|
||||||
BigInteger.ZERO,
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
op.evaluateBinary(1, 8, ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY),
|
op.evaluateBinary(1, 8, ff.getEncoding(b), ff.getEncoding(a)));
|
||||||
ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY)));
|
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(1, 8,
|
||||||
Assert.assertEquals(
|
ff.getBigInfinityEncoding(false), ff.getBigInfinityEncoding(false)));
|
||||||
BigInteger.ONE,
|
Assert.assertEquals(BigInteger.ONE, op.evaluateBinary(1, 8,
|
||||||
op.evaluateBinary(1, 8, ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY),
|
ff.getBigInfinityEncoding(false), ff.getBigInfinityEncoding(true)));
|
||||||
ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY)));
|
Assert.assertEquals(BigInteger.ZERO, op.evaluateBinary(1, 8,
|
||||||
Assert.assertEquals(
|
ff.getBigInfinityEncoding(true), ff.getBigInfinityEncoding(true)));
|
||||||
BigInteger.ZERO,
|
Assert.assertEquals(BigInteger.ONE,
|
||||||
op.evaluateBinary(1, 8, ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY),
|
op.evaluateBinary(1, 8, ff.getBigInfinityEncoding(false), ff.getBigNaNEncoding(false)));
|
||||||
ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY)));
|
|
||||||
Assert.assertEquals(
|
|
||||||
BigInteger.ONE,
|
|
||||||
op.evaluateBinary(1, 8, ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY),
|
|
||||||
ff.getEncoding(FloatFormat.BIG_NaN)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -81,44 +80,41 @@ public class OpBehaviorFloatRoundTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigInteger a = ff.getEncoding(BigDecimal.valueOf(2.5d));
|
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
|
||||||
BigInteger result = op.evaluateUnary(8, 8, a);
|
BigInteger result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(3.0d).stripTrailingZeros(), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(3.0d), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(2.25d));
|
a = ff.getEncoding(ff.getBigFloat(2.25d));
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(2.0d).stripTrailingZeros(), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(2.0d), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(2.75d));
|
a = ff.getEncoding(ff.getBigFloat(2.75d));
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(3.0d).stripTrailingZeros(), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(3.0d), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(-2.5d));
|
a = ff.getEncoding(ff.getBigFloat(-2.5d));
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(-2.0d).stripTrailingZeros(),
|
Assert.assertEquals(ff.getBigFloat(-2.0d), ff.getHostFloat(result));
|
||||||
ff.getHostFloat(result));
|
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(-2.25d));
|
a = ff.getEncoding(ff.getBigFloat(-2.25d));
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(-2.0d).stripTrailingZeros(),
|
Assert.assertEquals(ff.getBigFloat(-2.0d), ff.getHostFloat(result));
|
||||||
ff.getHostFloat(result));
|
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(-2.75d));
|
a = ff.getEncoding(ff.getBigFloat(-2.75d));
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(-3.0d).stripTrailingZeros(),
|
Assert.assertEquals(ff.getBigFloat(-3.0d), ff.getHostFloat(result));
|
||||||
ff.getHostFloat(result));
|
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(false);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_POSITIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(true);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NEGATIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NaN);
|
a = ff.getBigNaNEncoding(false);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(FloatFormat.BIG_NaN, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,14 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ghidra.pcode.floatformat.FloatFormat;
|
import ghidra.pcode.floatformat.*;
|
||||||
import ghidra.pcode.floatformat.FloatFormatFactory;
|
|
||||||
|
|
||||||
public class OpBehaviorFloatSqrtTest extends AbstractOpBehaviorTest {
|
public class OpBehaviorFloatSqrtTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
|
@ -30,8 +28,8 @@ public class OpBehaviorFloatSqrtTest extends AbstractOpBehaviorTest {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryLong() {
|
public void testEvaluateBinaryLong() {
|
||||||
|
|
||||||
OpBehaviorFloatSqrt op = new OpBehaviorFloatSqrt();
|
OpBehaviorFloatSqrt op = new OpBehaviorFloatSqrt();
|
||||||
|
|
||||||
|
@ -44,19 +42,18 @@ public class OpBehaviorFloatSqrtTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryBigInteger() {
|
public void testEvaluateBinaryBigInteger() {
|
||||||
|
|
||||||
OpBehaviorFloatSqrt op = new OpBehaviorFloatSqrt();
|
OpBehaviorFloatSqrt op = new OpBehaviorFloatSqrt();
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigDecimal big = BigDecimal.valueOf(2.0);
|
BigFloat big = ff.getBigFloat(2.0);
|
||||||
BigInteger encoding = ff.getEncoding(big);
|
BigInteger encoding = ff.getEncoding(big);
|
||||||
encoding = op.evaluateUnary(8, 8, encoding);
|
encoding = op.evaluateUnary(8, 8, encoding);
|
||||||
BigDecimal result = ff.getHostFloat(encoding);
|
BigFloat result = ff.getHostFloat(encoding);
|
||||||
Assert.assertEquals("1.414213562373095", result.toString());
|
Assert.assertEquals("1.414213562373095", ff.round(result).toString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -75,35 +74,35 @@ public class OpBehaviorFloatSubTest extends AbstractOpBehaviorTest {
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigInteger a = ff.getEncoding(BigDecimal.valueOf(1.5d));
|
BigInteger a = ff.getEncoding(ff.getBigFloat(1.5d));
|
||||||
BigInteger b = ff.getEncoding(BigDecimal.valueOf(1.25d));
|
BigInteger b = ff.getEncoding(ff.getBigFloat(1.25d));
|
||||||
BigInteger result = op.evaluateBinary(8, 8, a, b);// 1.5 - 1.25
|
BigInteger result = op.evaluateBinary(8, 8, a, b);// 1.5 - 1.25
|
||||||
Assert.assertEquals(BigDecimal.valueOf(0.25d), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(0.25d), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(-1.25d));
|
a = ff.getEncoding(ff.getBigFloat(-1.25d));
|
||||||
result = op.evaluateBinary(8, 8, a, b);// -1.25 - 1.25
|
result = op.evaluateBinary(8, 8, a, b);// -1.25 - 1.25
|
||||||
Assert.assertEquals(BigDecimal.valueOf(-2.5d), ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigFloat(-2.5d), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(false);
|
||||||
result = op.evaluateBinary(8, 8, a, b);// +INFINITY - 1.25
|
result = op.evaluateBinary(8, 8, a, b);// +INFINITY - 1.25
|
||||||
Assert.assertEquals(FloatFormat.BIG_POSITIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(true);
|
||||||
result = op.evaluateBinary(8, 8, a, b);// -INFINITY - 1.25
|
result = op.evaluateBinary(8, 8, a, b);// -INFINITY - 1.25
|
||||||
Assert.assertEquals(FloatFormat.BIG_NEGATIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
|
||||||
|
|
||||||
b = ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY);
|
b = ff.getBigInfinityEncoding(true);
|
||||||
result = op.evaluateBinary(8, 8, a, b);// -INFINITY - -INFINITY
|
result = op.evaluateBinary(8, 8, a, b);// -INFINITY - -INFINITY
|
||||||
Assert.assertEquals(FloatFormat.BIG_NaN, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
b = ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY);
|
b = ff.getBigInfinityEncoding(false);
|
||||||
result = op.evaluateBinary(8, 8, a, b);// -INFINITY - +INFINITY
|
result = op.evaluateBinary(8, 8, a, b);// -INFINITY - +INFINITY
|
||||||
Assert.assertEquals(FloatFormat.BIG_NEGATIVE_INFINITY, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigInfinity(true), ff.getHostFloat(result));
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NaN);
|
a = ff.getBigNaNEncoding(false);
|
||||||
b = ff.getEncoding(BigDecimal.valueOf(1.25d));
|
b = ff.getEncoding(ff.getBigFloat(1.25d));
|
||||||
result = op.evaluateBinary(8, 8, a, b);// NaN - 1.25
|
result = op.evaluateBinary(8, 8, a, b);// NaN - 1.25
|
||||||
Assert.assertEquals(FloatFormat.BIG_NaN, ff.getHostFloat(result));
|
Assert.assertEquals(ff.getBigNaN(false), ff.getHostFloat(result));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.pcode.opbehavior;
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -30,8 +29,8 @@ public class OpBehaviorFloatTruncTest extends AbstractOpBehaviorTest {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryLong() {
|
public void testEvaluateBinaryLong() {
|
||||||
|
|
||||||
OpBehaviorFloatTrunc op = new OpBehaviorFloatTrunc();
|
OpBehaviorFloatTrunc op = new OpBehaviorFloatTrunc();
|
||||||
|
|
||||||
|
@ -59,31 +58,31 @@ public class OpBehaviorFloatTruncTest extends AbstractOpBehaviorTest {
|
||||||
Assert.assertEquals(0, result);
|
Assert.assertEquals(0, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEvaluateBinaryBigInteger() {
|
public void testEvaluateBinaryBigInteger() {
|
||||||
|
|
||||||
OpBehaviorFloatTrunc op = new OpBehaviorFloatTrunc();
|
OpBehaviorFloatTrunc op = new OpBehaviorFloatTrunc();
|
||||||
|
|
||||||
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
FloatFormat ff = FloatFormatFactory.getFloatFormat(8);
|
||||||
|
|
||||||
BigInteger a = ff.getEncoding(BigDecimal.valueOf(2.5d));
|
BigInteger a = ff.getEncoding(ff.getBigFloat(2.5d));
|
||||||
BigInteger result = op.evaluateUnary(8, 8, a);
|
BigInteger result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigInteger.valueOf(2), result);
|
Assert.assertEquals(BigInteger.valueOf(2), result);
|
||||||
|
|
||||||
a = ff.getEncoding(BigDecimal.valueOf(-2.5d));
|
a = ff.getEncoding(ff.getBigFloat(-2.5d));
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigInteger.valueOf(-2), result);
|
Assert.assertEquals(BigInteger.valueOf(-2), result);
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_POSITIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(false);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigInteger.valueOf(Long.MAX_VALUE), result);
|
Assert.assertEquals(BigInteger.valueOf(Long.MAX_VALUE), result);
|
||||||
|
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NEGATIVE_INFINITY);
|
a = ff.getBigInfinityEncoding(true);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigInteger.valueOf(Long.MIN_VALUE), result);
|
Assert.assertEquals(BigInteger.valueOf(Long.MIN_VALUE), result);
|
||||||
|
|
||||||
// TODO: What should the correct result be?
|
// TODO: What should the correct result be?
|
||||||
a = ff.getEncoding(FloatFormat.BIG_NaN);
|
a = ff.getBigNaNEncoding(false);
|
||||||
result = op.evaluateUnary(8, 8, a);
|
result = op.evaluateUnary(8, 8, a);
|
||||||
Assert.assertEquals(BigInteger.ZERO, result);
|
Assert.assertEquals(BigInteger.ZERO, result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.model.data;
|
package ghidra.program.model.data;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.*;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -46,39 +46,43 @@ public class Float10DataTypeTest extends AbstractGTest {
|
||||||
|
|
||||||
// Really small values
|
// Really small values
|
||||||
|
|
||||||
|
MathContext mc = new MathContext(18, RoundingMode.UP);
|
||||||
|
|
||||||
bytes = bytes(0, 1, 0x80, 0, 0, 0, 0, 0, 0, 0); // 0x00018000000000000000 = approaches 0
|
bytes = bytes(0, 1, 0x80, 0, 0, 0, 0, 0, 0, 0); // 0x00018000000000000000 = approaches 0
|
||||||
value =
|
value =
|
||||||
Float10DataType.dataType.getValue(new ByteMemBufferImpl(null, bytes, true), null, 10);
|
Float10DataType.dataType.getValue(new ByteMemBufferImpl(null, bytes, true), null, 10);
|
||||||
Assert.assertEquals("5.04315471466814026E-4932", value.toString());
|
Assert.assertEquals("5.04315471466814026E-4932", ((BigDecimal) value).round(mc).toString());
|
||||||
|
|
||||||
bytes = bytes(0x80, 1, 0x80, 0, 0, 0, 0, 0, 0, 0); // 0x00018000000000000000 = approaches 0
|
bytes = bytes(0x80, 1, 0x80, 0, 0, 0, 0, 0, 0, 0); // 0x00018000000000000000 = approaches 0
|
||||||
value =
|
value =
|
||||||
Float10DataType.dataType.getValue(new ByteMemBufferImpl(null, bytes, true), null, 10);
|
Float10DataType.dataType.getValue(new ByteMemBufferImpl(null, bytes, true), null, 10);
|
||||||
Assert.assertEquals("-5.04315471466814026E-4932", value.toString());
|
Assert.assertEquals("-5.04315471466814026E-4932",
|
||||||
|
((BigDecimal) value).round(mc).toString());
|
||||||
|
|
||||||
// Really big values
|
// Really big values
|
||||||
|
|
||||||
bytes = bytes(0x7f, 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0); // 0x7ffe8000000000000000 = approaches +infinity
|
bytes = bytes(0x7f, 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0); // 0x7ffe8000000000000000 = approaches +infinity
|
||||||
value =
|
value =
|
||||||
Float10DataType.dataType.getValue(new ByteMemBufferImpl(null, bytes, true), null, 10);
|
Float10DataType.dataType.getValue(new ByteMemBufferImpl(null, bytes, true), null, 10);
|
||||||
Assert.assertEquals("8.92298621517923824E+4931", value.toString());
|
Assert.assertEquals("8.92298621517923824E+4931", ((BigDecimal) value).round(mc).toString());
|
||||||
|
|
||||||
bytes = bytes(0xff, 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0); // 0x7ffe8000000000000000 = approaches -infinity
|
bytes = bytes(0xff, 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0); // 0x7ffe8000000000000000 = approaches -infinity
|
||||||
value =
|
value =
|
||||||
Float10DataType.dataType.getValue(new ByteMemBufferImpl(null, bytes, true), null, 10);
|
Float10DataType.dataType.getValue(new ByteMemBufferImpl(null, bytes, true), null, 10);
|
||||||
Assert.assertEquals("-8.92298621517923824E+4931", value.toString());
|
Assert.assertEquals("-8.92298621517923824E+4931",
|
||||||
|
((BigDecimal) value).round(mc).toString());
|
||||||
|
|
||||||
// Values within the range of Double
|
// Values within the range of Double
|
||||||
|
|
||||||
bytes = bytes(0x40, 1, 0x20, 0, 0, 0, 0, 0, 0, 0); // 0x40002000000000000000 = approaches -infinity
|
bytes = bytes(0x40, 1, 0x20, 0, 0, 0, 0, 0, 0, 0); // 0x40002000000000000000 = approaches -infinity
|
||||||
value =
|
value =
|
||||||
Float10DataType.dataType.getValue(new ByteMemBufferImpl(null, bytes, true), null, 10);
|
Float10DataType.dataType.getValue(new ByteMemBufferImpl(null, bytes, true), null, 10);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(4.5), value);
|
Assert.assertEquals(BigDecimal.valueOf(4.5), ((BigDecimal) value).stripTrailingZeros());
|
||||||
|
|
||||||
bytes = bytes(0xc0, 1, 0x20, 0, 0, 0, 0, 0, 0, 0); // 0x40002000000000000000 = approaches -infinity
|
bytes = bytes(0xc0, 1, 0x20, 0, 0, 0, 0, 0, 0, 0); // 0x40002000000000000000 = approaches -infinity
|
||||||
value =
|
value =
|
||||||
Float10DataType.dataType.getValue(new ByteMemBufferImpl(null, bytes, true), null, 10);
|
Float10DataType.dataType.getValue(new ByteMemBufferImpl(null, bytes, true), null, 10);
|
||||||
Assert.assertEquals(BigDecimal.valueOf(-4.5), value);
|
Assert.assertEquals(BigDecimal.valueOf(-4.5), ((BigDecimal) value).stripTrailingZeros());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue