/*
** Copyright (C) 2018 Martin Brain
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see .
*/
// DEPRECIATED : USE implementation.h instead
/*
** executable.h
**
** Martin Brain
** martin.brain@cs.ox.ac.uk
** 06/08/14
**
** A set of basic functions constructed from the simple executable
** implementation of bit-vectors.
**
*/
#include
#include
#include
#include "symfpu/core/unpackedFloat.h"
#include "symfpu/core/packing.h"
#include "symfpu/core/sign.h"
#include "symfpu/core/classify.h"
#include "symfpu/core/compare.h"
#include "symfpu/core/multiply.h"
#include "symfpu/core/add.h"
#ifndef SYMFPU_EXECUTABLE
#define SYMFPU_EXECUTABLE
template
class executableTests {
public :
// Wrapped in a struct to make type scoping easier
// and to save on typenames.
// Object is stateless.
typedef typename traits::rm rm;
typedef typename traits::bwt bwt;
typedef typename traits::fpt fpt;
typedef typename traits::ubv ubv;
typedef typename traits::prop prop;
typedef symfpu::unpackedFloat uf;
static bwt bitsInExecBV () {
return sizeof(execBV) * CHAR_BIT;
}
static execBV unpackPack (const fpt &format, const execBV bv) {
ubv packed(bitsInExecBV(),bv);
uf unpacked(symfpu::unpack(format, packed));
ubv repacked(symfpu::pack(format, unpacked));
return repacked.contents();
}
static execBV unpackPackReference (const fpt &, execBV bv) {
return bv;
}
static execBV negate (const fpt &format, execBV bv) {
ubv packed(bitsInExecBV(),bv);
uf unpacked(symfpu::unpack(format, packed));
uf negated(symfpu::negate(format, unpacked));
ubv repacked(symfpu::pack(format, negated));
return repacked.contents();
}
static execBV negateReference (const fpt &, execBV bv) {
execFloat f = *((execFloat *)&bv);
f = -f;
return *((execBV *)&f);
}
static execBV absolute (const fpt &format, execBV bv) {
ubv packed(bitsInExecBV(),bv);
uf unpacked(symfpu::unpack(format, packed));
uf abs(symfpu::absolute(format, unpacked));
ubv repacked(symfpu::pack(format, abs));
return repacked.contents();
}
static execBV absoluteReference (const fpt &, execBV bv) {
execFloat f = *((execFloat *)&bv);
f = nativeFunctions::abs(f);
return *((execBV *)&f);
}
static bool isNormal (const fpt &format, execBV bv) {
ubv packed(bitsInExecBV(),bv);
uf unpacked(symfpu::unpack(format, packed));
prop result(symfpu::isNormal(format, unpacked));
return result;
}
static bool isNormalReference (const fpt &, execBV bv) {
execFloat f = *((execFloat *)&bv);
return nativeFunctions::isNormal(f);
}
static bool isSubnormal (const fpt &format, execBV bv) {
ubv packed(bitsInExecBV(),bv);
uf unpacked(symfpu::unpack(format, packed));
prop result(symfpu::isSubnormal(format, unpacked));
return result;
}
static bool isSubnormalReference (const fpt &, execBV bv) {
execFloat f = *((execFloat *)&bv);
return nativeFunctions::isSubnormal(f);
}
static bool isZero (const fpt &format, execBV bv) {
ubv packed(bitsInExecBV(),bv);
uf unpacked(symfpu::unpack(format, packed));
prop result(symfpu::isZero(format, unpacked));
return result;
}
static bool isZeroReference (const fpt &, execBV bv) {
execFloat f = *((execFloat *)&bv);
return nativeFunctions::isZero(f);
}
static bool isInfinite (const fpt &format, execBV bv) {
ubv packed(bitsInExecBV(),bv);
uf unpacked(symfpu::unpack(format, packed));
prop result(symfpu::isInfinite(format, unpacked));
return result;
}
static bool isInfiniteReference (const fpt &, execBV bv) {
execFloat f = *((execFloat *)&bv);
return nativeFunctions::isInf(f);
}
static bool isNaN (const fpt &format, execBV bv) {
ubv packed(bitsInExecBV(),bv);
uf unpacked(symfpu::unpack(format, packed));
prop result(symfpu::isNaN(format, unpacked));
return result;
}
static bool isNaNReference (const fpt &, execBV bv) {
execFloat f = *((execFloat *)&bv);
return nativeFunctions::isNaN(f);
}
static bool isPositive (const fpt &format, execBV bv) {
ubv packed(bitsInExecBV(),bv);
uf unpacked(symfpu::unpack(format, packed));
prop result(symfpu::isPositive(format, unpacked));
return result;
}
static bool isPositiveReference (const fpt &, execBV bv) {
execFloat f = *((execFloat *)&bv);
return nativeFunctions::isPositive(f);
}
static bool isNegative (const fpt &format, execBV bv) {
ubv packed(bitsInExecBV(),bv);
uf unpacked(symfpu::unpack(format, packed));
prop result(symfpu::isNegative(format, unpacked));
return result;
}
static bool isNegativeReference (const fpt &, execBV bv) {
execFloat f = *((execFloat *)&bv);
return nativeFunctions::isNegative(f);
}
static bool smtlibEqual (const fpt &format, execBV bv1, execBV bv2) {
ubv packed1(bitsInExecBV(),bv1);
ubv packed2(bitsInExecBV(),bv2);
uf unpacked1(symfpu::unpack(format, packed1));
uf unpacked2(symfpu::unpack(format, packed2));
prop result(symfpu::smtlibEqual(format, unpacked1, unpacked2));
return result;
}
static bool smtlibEqualReference (const fpt &, execBV bv1, execBV bv2) {
execFloat f = *((execFloat *)(&bv1));
execFloat g = *((execFloat *)(&bv2));
return (bv1 == bv2) || (nativeFunctions::isNaN(f) && nativeFunctions::isNaN(g));
}
static bool ieee754Equal (const fpt &format, execBV bv1, execBV bv2) {
ubv packed1(bitsInExecBV(),bv1);
ubv packed2(bitsInExecBV(),bv2);
uf unpacked1(symfpu::unpack(format, packed1));
uf unpacked2(symfpu::unpack(format, packed2));
prop result(symfpu::ieee754Equal(format, unpacked1, unpacked2));
return result;
}
static bool ieee754EqualReference (const fpt &, execBV bv1, execBV bv2) {
execFloat f = *((execFloat *)(&bv1));
execFloat g = *((execFloat *)(&bv2));
return (f == g);
}
static bool lessThan (const fpt &format, execBV bv1, execBV bv2) {
ubv packed1(bitsInExecBV(),bv1);
ubv packed2(bitsInExecBV(),bv2);
uf unpacked1(symfpu::unpack(format, packed1));
uf unpacked2(symfpu::unpack(format, packed2));
prop result(symfpu::lessThan(format, unpacked1, unpacked2));
return result;
}
static bool lessThanReference (const fpt &, execBV bv1, execBV bv2) {
execFloat f = *((execFloat *)(&bv1));
execFloat g = *((execFloat *)(&bv2));
return (f < g);
}
static bool lessThanOrEqual (const fpt &format, execBV bv1, execBV bv2) {
ubv packed1(bitsInExecBV(),bv1);
ubv packed2(bitsInExecBV(),bv2);
uf unpacked1(symfpu::unpack(format, packed1));
uf unpacked2(symfpu::unpack(format, packed2));
prop result(symfpu::lessThanOrEqual(format, unpacked1, unpacked2));
return result;
}
static bool lessThanOrEqualReference (const fpt &, execBV bv1, execBV bv2) {
execFloat f = *((execFloat *)(&bv1));
execFloat g = *((execFloat *)(&bv2));
return (f <= g);
}
static execBV multiply (const fpt &format, const rm &roundingMode, execBV bv1, execBV bv2) {
ubv packed1(bitsInExecBV(),bv1);
ubv packed2(bitsInExecBV(),bv2);
uf unpacked1(symfpu::unpack(format, packed1));
uf unpacked2(symfpu::unpack(format, packed2));
uf multiplied(symfpu::multiply(format, roundingMode, unpacked1, unpacked2));
ubv repacked(symfpu::pack(format, multiplied));
return repacked.contents();
}
static execBV multiplyReference (const fpt &, const rm &roundingMode, execBV bv1, execBV bv2) {
execFloat f = *((execFloat *)(&bv1));
execFloat g = *((execFloat *)(&bv2));
fesetround(roundingMode.getValue());
execFloat h = f * g;
return *((execBV *)&h);
}
static execBV add (const fpt &format, const rm &roundingMode, execBV bv1, execBV bv2) {
ubv packed1(bitsInExecBV(),bv1);
ubv packed2(bitsInExecBV(),bv2);
uf unpacked1(symfpu::unpack(format, packed1));
uf unpacked2(symfpu::unpack(format, packed2));
uf added(symfpu::add(format, roundingMode, unpacked1, unpacked2, prop(true)));
ubv repacked(symfpu::pack(format, added));
return repacked.contents();
}
static execBV addReference (const fpt &, const rm &roundingMode, execBV bv1, execBV bv2) {
execFloat f = *((execFloat *)(&bv1));
execFloat g = *((execFloat *)(&bv2));
fesetround(roundingMode.getValue());
execFloat h = f + g;
return *((execBV *)&h);
}
static execBV sub (const fpt &format, const rm &roundingMode, execBV bv1, execBV bv2) {
ubv packed1(bitsInExecBV(),bv1);
ubv packed2(bitsInExecBV(),bv2);
uf unpacked1(symfpu::unpack(format, packed1));
uf unpacked2(symfpu::unpack(format, packed2));
uf added(symfpu::add(format, roundingMode, unpacked1, unpacked2, prop(false)));
ubv repacked(symfpu::pack(format, added));
return repacked.contents();
}
static execBV subReference (const fpt &, const rm &roundingMode, execBV bv1, execBV bv2) {
execFloat f = *((execFloat *)(&bv1));
execFloat g = *((execFloat *)(&bv2));
fesetround(roundingMode.getValue());
execFloat h = f - g;
return *((execBV *)&h);
}
// The SMT-LIB notion of equality
//bool compareFloat (execBV bv1, execBV bv2);
};
#endif