/* ** 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