universal: Quire += operator seems to fail

I’m working with posit<16,1> at the moment. Modeling quire usage after the code in examples/blas/blas.hpp line 62, I have the following:

for(int row=0; row<n; ++row) {
     quireX sum = sw::unum::quire_mul(beta, ycoefs[row]); //sum is initially 0
     for(LocalOrdinalType i=Arowoffsets[row]; i<Arowoffsets[row+1]; ++i) {
          positX tempPosit; 
          sum += sw::unum::quire_mul(Acoefs[i], xcoefs[Acols[i]]);
          if (row > 263 && row < 269) {
               tempPosit.convert(sum.to_value());
               if (tempPosit < testCompare) {
                        std::cout <<"WRONG! Sum after += is less than -1.0: " << tempPosit <<", after taking sum (" << sumHolderPosit << ") += quire_mul("<<Acoefs[i] << ", " <<xcoefs[Acols[i]] << ")" << std::endl;
                        std::cout <<"We essentially took " << sumHolderPosit << " += " << tempQuireMultholder << " and somehow ended up with " << tempPosit << std::endl;
                        std::cout << "Incorrect sum as a quire: " << sum << std::endl;
                        std::cout << "Delta Quire: " << tempQuireMult << ", (as posit) = " << tempQuireMultholder << std::endl;
                        std::cout << "Row: " << row << ", Acoefs[i]: " << Acoefs[i] << ", Acols[i]: " << Acols[i] << ", xcoefs[" << Acols[i] << "]: " << xcoefs[Acols[i]] << std::endl;
               }
          }

The sum should never go below the value -1.0 - and if I run an alternate version of this code that does not use the quire feature, it doesn’t. With the quire enabled, I get the following output - the WRONG! tag near the bottom is where the error occurs - I figured I’d include additional output prior to the error of the sum successfully reducing in size.

Row is 266. Acoefs[5334] = -0.016571, xcoefs[Acols[5334]] = 0.000999451
Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000001100000110001100000010000000000000000000000
Sum before += quire_mul (as posit)9.25064e-05
product of quire_mul = -1.66893e-05
Row is 266. Acoefs[5335] = -0.00828552, xcoefs[Acols[5335]] = 0.000999451
Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000001001111011010000011010000000000000000000000
Sum before += quire_mul (as posit)7.53403e-05
product of quire_mul = -8.10623e-06
Row is 266. Acoefs[5336] = -0.0165405, xcoefs[Acols[5336]] = 0.000999451
Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000001000110101110010100110000000000000000000000
Sum before += quire_mul (as posit)6.77109e-05
product of quire_mul = -1.66893e-05
Row is 266. Acoefs[5337] = 7.62939e-06, xcoefs[Acols[5337]] = 0.000999451
Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000000110101011000111010110000000000000000000000
Sum before += quire_mul (as posit)5.05447e-05
product of quire_mul = 1.49012e-08
Row is 266. Acoefs[5338] = -0.0165405, xcoefs[Acols[5338]] = 0.000999451
Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000000110101011001011011100000000000000000000000
Sum before += quire_mul (as posit)5.05447e-05
product of quire_mul = -1.66893e-05
Row is 266. Acoefs[5339] = -0.00828552, xcoefs[Acols[5339]] = 0.000999451
Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000000100100000100000001100000000000000000000000
Sum before += quire_mul (as posit)3.43323e-05
product of quire_mul = -8.10623e-06
Row is 266. Acoefs[5340] = -0.016571, xcoefs[Acols[5340]] = 0.000999451
Sum before += quire_mul  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000000011011011000010011000000000000000000000000
Sum before += quire_mul (as posit)2.6226e-05
product of quire_mul = -1.66893e-05
-------------------------------------------------------------------------------------------------------------------
WRONG! Sum after += is less than -1.0: -2.68435e+08, after taking sum (2.6226e-05) += quire_mul(-0.016571, 0.000999451)
We essentially took 2.6226e-05 += -1.66893e-05 and somehow ended up with -2.68435e+08 (= -maxpos)
Incorrect sum as a quire: -1: 111111111111111111111111111111_111111111111111111111111111111111111111111111111111111111.11111111111111110101111111001010000000000000000000000000
Delta Quire: -1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000000010001010111011101000000000000000000000000, (as posit) = -1.66893e-05
Row: 266, Acoefs[i]: -0.016571, Acols[i]: 398, xcoefs[398]: 0.000999451
Row is 266. Acoefs[5341] = -0.00828552, xcoefs[Acols[5341]] = 0.000999451
-------------------------------------------------------------------------------------------------------------------

If you noticed, the value -2.68435e+08 is negative maxpos for a <16,1> posit. So what I’m wondering is, why does my quire suddenly explode from very small positive values to massive negative values?

My positX and quireX are declared as

namespace posit_shape {
    const uint es = UNUM_ES_SIZE; //1
    const uint nbits = UNUM_NBIT_SIZE; //16
}
namespace quire_shape {
    const uint es = UNUM_ES_SIZE;
    const uint nbits = UNUM_NBIT_SIZE;
    const uint capacity = UNUM_QUIRE_CAPACITY; //10 - as per stillwater example
}
typedef sw::unum::posit<posit_shape::nbits, posit_shape::es> positX;
typedef sw::unum::quire<quire_shape::nbits, quire_shape::es> quireX;

All evidence points to a bug in quire’s +=, any feedback welcome.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 18 (10 by maintainers)

Most upvoted comments

A quick test of the values that caused the breakdown:

int main() {

    quireX sum = 2.6226e-05;
    positX sumAsPosit;
    positX argA = -0.016571;
    positX argB = 0.000999451;
    sumAsPosit.convert(sum.to_value());
    std::cout << "sum = " << sum << std::endl;
    std::cout << "sumAsPosit = " << sumAsPosit << std::endl;
    sum += sw::unum::quire_mul(argA, argB);
    std::cout << "sum after += == " << sum << std::endl;
    sumAsPosit.convert(sum.to_value());
    std::cout << "sum after +=(as posit) == " << sumAsPosit << std::endl;
    return 0;
}

Generates the following output:

sum =  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000000011011011111111111110011111111001100110110
sumAsPosit = 2.6226e-05
sum after += ==  1: 000000000000000000000000000000_000000000000000000000000000000000000000000000000000000000.00000000000000001010001000100010110011111111001100110110
sum after +=(as posit) == 9.53674e-06

Process finished with exit code 0

Doing the calculation manually gives me about the same answer (finite accuracy curve). So += seems to be solid for these values.