template <int bits, typename SymbolCoder> void writer(SymbolCoder& coder, int min, int max, int value) { assert(min<=max); assert(value>=min); assert(value<=max); // avoid doing anything if the value is already known if (min == max) return; if (value == 0) { // value is zero coder.write(true, BIT_ZERO); return; } // only output zero bit if value could also have been zero if (max >= 0 && min <= 0) coder.write(false,BIT_ZERO); int sign = (value > 0 ? 1 : 0); if (max > 0 && min < 0) { // only output sign bit if value can be both pos and neg if (min < 0 && max > 0) coder.write(sign,BIT_SIGN); } if (sign && min <= 0) min = 1; if (!sign && max >= 0) max = -1; const int a = abs(value); const int e = maniac::util::ilog2(a); int amin = sign ? abs(min) : abs(max); int amax = sign ? abs(max) : abs(min); int emax = maniac::util::ilog2(amax); int i = maniac::util::ilog2(amin); while (i < emax) { // if exponent >i is impossible, we are done if ((1 << (i+1)) > amax) break; // if exponent i is possible, output the exponent bit coder.write(i==e, BIT_EXP, i); if (i==e) break; i++; } // e_printf("exp=%i\n",e); int have = (1 << e); int left = have-1; for (int pos = e; pos>0;) { int bit = 1; left ^= (1 << (--pos)); int minabs1 = have | (1<<pos); // int maxabs1 = have | left | (1<<pos); // int minabs0 = have; int maxabs0 = have | left; if (minabs1 > amax) { // 1-bit is impossible bit = 0; } else if (maxabs0 >= amin) { // 0-bit and 1-bit are both possible bit = (a >> pos) & 1; coder.write(bit, BIT_MANT, pos); } have |= (bit << pos); }
template <int bits, typename SymbolCoder> int reader(SymbolCoder& coder, int min, int max) { assert(min<=max); if (min == max) return min; bool sign; assert(min <= 0 && max >= 0); // should always be the case, because guess should always be in valid range // if (max >= 0 && min <= 0) { if (coder.read(BIT_ZERO)) return 0; if (min < 0) { if (max > 0) { sign = coder.read(BIT_SIGN); if (sign) min = 1; else max = -1; } else {sign = false; max=-1;} } else {sign = true; min=1;} // } else { // max < 0 || min > 0 // if (min<0) sign = false; // else sign = true; // } const int amin = (sign? min : -max); const int amax = (sign? max : -min); const int emax = maniac::util::ilog2(amax); int e = maniac::util::ilog2(amin); //for (; e < emax; e++) { for (; e < emax; e++) { // if exponent >e is impossible, we are done // actually that cannot happen //if ((1 << (e+1)) > amax) break; if (coder.read(BIT_EXP,(e<<1)+sign)) break; } int have = (1 << e); int left = have-1; for (int pos = e; pos>0;) { //int bit = 1; //left ^= (1 << (--pos)); left >>= 1; pos--; int minabs1 = have | (1<<pos); int maxabs0 = have | left; if (minabs1 > amax) { // 1-bit is impossible //bit = 0; continue; } else if (maxabs0 >= amin) { // 0-bit and 1-bit are both possible //bit = coder.read(BIT_MANT,pos); if (coder.read(BIT_MANT,pos)) have = minabs1; } // else 0-bit is impossible, so bit stays 1 else have = minabs1; //have |= (bit << pos); } return (sign ? have : -have); }
template <int bits, typename SymbolCoder> int reader(SymbolCoder& coder, int min, int max) { assert(min<=max); if (min == max) return min; bool sign; if (max >= 0 && min <= 0) { if (coder.read(BIT_ZERO)) return 0; if (min < 0) { if (max > 0) { sign = coder.read(BIT_SIGN); if (sign) min = 1; else max = -1; } else {sign = false; max=-1;} } else {sign = true; min=1;} // if (min == max) return min; // nodig? } else { if (min<0) sign = false; else sign = true; } // if (sign && min <= 0) min = 1; // if (!sign && max >= 0) max = -1; int amin = (sign? min : -max); int amax = (sign? max : -min); int emax = maniac::util::ilog2(amax); int i = maniac::util::ilog2(amin); for (; i < emax; i++) { // if exponent >i is impossible, we are done if ((1 << (i+1)) > amax) break; if (coder.read(BIT_EXP,i)) break; } int e = i; int have = (1 << e); int left = have-1; for (int pos = e; pos>0;) { int bit = 1; left ^= (1 << (--pos)); int minabs1 = have | (1<<pos); int maxabs0 = have | left; if (minabs1 > amax) { // 1-bit is impossible bit = 0; } else if (maxabs0 >= amin) { // 0-bit and 1-bit are both possible bit = coder.read(BIT_MANT,pos); } have |= (bit << pos); } return (sign ? have : -have); }
template <typename SymbolCoder> void writer(SymbolCoder& coder, int bits, int value) { int pos=0; while (pos++ < bits) { coder.write(value&1, BIT_MANT, pos); value >>= 1; } }
template <typename SymbolCoder> int reader(SymbolCoder& coder, int bits) { int pos=0; int value=0; int b=1; while (pos++ < bits) { if (coder.read(BIT_MANT, pos)) value += b; b *= 2; } return value; }