# Machine FP partial invariance issue

## Invariance issue

In computer representation:

“a + b + c” and “a + c + b” is not the same!
(and not the samefor multiplicationas well).

Hallelujah! I finally got that simple fact! After so many years of working in IT industry and software development!Well, Ikind of knew this, but never took it seriously until recently
If you guys are curious how ape dealt with getting bananatask
If you are same late as I am, read bellow.

## Floating point machine representation

Usuallynumber is represented as follows:
v = m * (be)

Where

m– is the mantissa, an integer with limited range. For example, for decimal numbers it could be in range from 0 to 99. For 24 bit binary numbers it is in range from 0 to (224-1), or from 0 to 16777215.
b– is the base, usually b = 2, an integer value,
e– is exponent, integer, it could take both negative and positive values.
For example in decimal numbers representation 0.5 is represented as:
0.5 = 5 * 10-1 (here m=5, b=10, e=-1)
For binary numbers 0.5 is 2-1 (m=1, b=2, e=-1)

Some people know, that in order to store bigger numbers we need more space in memory. But bigger precision also requires more memory, for we need mantissa of greater width, and thus we also need more bits to store it.

## Integer vs float

While working with regular integer numbers we also having data loss and overflow issues, and yet we’re able to control it. We keep in mind minimum and maximum possible integer results, and this know when overflow might happen.
Floating point numbers is different. AFAIK no sane people control mantissa overflow, except perhaps some really rare cases. So here, better to think it just happens all the time.

## Inevitable data loss

It is impossible to store numbers with infinite precision, and thus, data loss is inevitable. It’s obvious, but easy to miss if you had never dealt with some cases.
We can’t work with exact real number “N”…
We only able to work with its nearest machine floating pointrepresentation, fp(N) or:
N* = fp(N)

For mantissa in range 0 .. 999 we have next errors.
Number9999will be stored as
v = fp(9999) = 999e+1 = 9990
(here we lost info about most right “9”)

and number1.001will be stored just as
v = fp(1.001)=1
(here we lost info about most right “1”)

## a + b + c

Actually v = a + b + c is performed in two steps:
Step 1: x = a + b
Step 2: v = x + c
Or with respect to fp transformation:
Step 1: x = fp(a + b)
Step 2: v = fp(x + c)
By changing the order of sum components, we in fact change what we’re going to loss on each step. And by changing order of band c we get different data loss, just like a final result.

## Examples

Let’s demonstrate it on the next example.
• mantissa can store up to 2 decimal digits, and thus in range 0 .. 99.
• base is 10.
• exponent could be any, for it doesn’t matter here really.
Let’s use values:
a = 99 (m=99, e = 0)
b = 10 (m=1, e = 1)
c = 1 (m=1, e = 0)
And consider the difference of “a+b+c” and “a+c+b”:
a + b +c:
fp(a+b) = fp(99+10) = fp(109) = 100
v = fp( fp(a+b) + c ) = fp(100 + 1) = fp(101) = 100

a + c + b:
fp(a+c) = fp(99+1) = fp(100) = 100
v = fp( fp(a+c) + b ) = fp(100 + 10) = fp(110) = 110
Unbelievable for regular people, but so obvious to programmers (and yet unbelievable):
(a + b + c = 100) ≠ (a + c + b = 110)

Well, to be more correct:
( fp(a + b + c) = 100 ) ≠ ( fp(a + c + b) = 110)

## Upd:

As one of solutions, wider mantissa should be used for result, and only after all operation items participated in result, it then may be truncated to fp number with thinner mantissa.
If items have mantissa of N bits, then

• for sum of M+1 items result should have M+N  bits mantissa,
• for multiplication of M items result should have M*N bits mantissa.

Real example written on C is below.

example.c

`#include // Helpers declaration, for implementation scroll downfloat getAllOnes(unsigned bits);unsigned getmantissasaBits();int main() {  // Determine mantissasa size in bits  unsigned mantissasaBits = getmantissasaBits();  // Considering mantissasa has only 3 bits, we would then need:  // a = 0b10   m=1,  e=1  // b = 0b110  m=11, e=1  // c = 0b1000 m=1,  e=3  float a = 2,        b = getAllOnes(mantissasaBits) - 1,        c = b + 1;  float ab = a + b;  float ac = a + c;  float abc = a + b + c;  float acb = a + c + b;  printf("n"         "FP partial invariance issue demo:n"         "n"         "mantissasa size = %i bitsn"         "n"         "a = %.1fn"         "b = %.1fn"         "c = %.1fn"         "(a+b) result: %.1fn"         "(a+c) result: %.1fn"         "(a + b + c) result: %.1fn"         "(a + c + b) result: %.1fn"         "---------------------------------n"         "diff(a + b + c, a + c + b) = %.1fnn",         mantissasaBits,         a, b, c,         ab, ac,         abc, acb,         abc - acb);  return 1;}// Helpersfloat getAllOnes(unsigned bits) {    return (unsigned)((1 << bits) - 1);}unsigned getmantissasaBits() {    unsigned sz = 1;    unsigned unbeleivableHugeSize = 1024;    float allOnes = 1;    for (;sz != unbeleivableHugeSize &&          allOnes + 1 != allOnes;          allOnes = getAllOnes(++sz)          ) {}    return sz-1;}OutputFP partial invariance issue demo:mantissasa size = 24 bitsa = 2.0b = 16777214.0c = 16777215.0(a+b) result: 16777216.0(a+c) result: 16777216.0(a + b + c) result: 33554432.0(a + c + b) result: 33554430.0---------------------------------diff(a + b + c, a + c + b) = 2.0`

# Разрешение e-ink в YotaPhone 2

Господа, я стал счастливым обладателем YotaPhone 2! И вот мой вывод – телефон удобен. Но e-ink у него недоделан. Сейчас создается впечатление, что я всетаки переплатил. Однако разработчики этой компании славятся быстрой реакцией и регулярными правками ПО.

Итак (внизу есть UPD c более качественными фотками).

## Разрешение e-ink экрана.

В общем – полный бардак. Оно разное для разных приложений. То есть на программном уровне выставлено по разному. Как так?

### YotaCover

Самое лучшее, что мне удалось получить – это изображение для YotaCover. Там действительно можно наблюдать 235 dpi. Хотя и с некоторыми затруднениями.
Дело в том, что контрастность изображения настолько низкая, что его можно сравнить только, разве что, с первыми электронными книгами. Когда я положил рядом PocketBook 623 Touch 2 с разрешением 212 dpi, то у YotaPhone 2 не было просто никаких шансов. При более низком разрешении качество первого казалось просто полиграфическим. В то время, как на экране YotaPhone все было немного размыто. Я приложил сравнительный снимки. Для понимания масштаба положил  сверху волос.

PocketBook 623 Touch 2, 212 dpi
YotaPhone 2, 235 dpi

Да – у камеры другое фокусное расстояние в отличие от глаза, однако оно одинаково как для книги, так и для телефона, и отражает суть: минимальное расстояние перехода от полностью черной области экрана полностью белой на телефоне больше, а стало быть – контрастность ниже.
В чем причина низкой контрастности? Матовый экран? Но ведь даже ghost-effect  на вашем устройстве выглядит четче, чем само изображение. Возможно вы неправильно выставили разрешение; возможно – это качество самого e-ink экрана. Я все-таки надеюсь, что это проблема с разрешением и ее можно решить.

### Комфортное чтение

Так вот – оно не комфортное. Разрешение в этом режиме почти В ДВА РАЗА НИЖЕ. Это что, от первого YotaPhone настройки? Неужели было сложно конфиг подправить?
В общем. Тот, кто хоть раз читал с нормальной e-книги, останется очень недовольным качеством текста. Я также прилагаю снимок. Обратите внимание, как рисуются границы символов букв “т” и “д”: какими-то страшными точками.
Замечу, что если сделать скрин-шот самим телефоном, и потом посмотреть его на LED дисплее, то выглядит все очень четко, собственно – именно так, как и должно быть при 235 dpi. (При просмотре на LED дисплее, разумеется, нужно сделать небольшой zoom скриншота, чтоб получилось на весь экран.)

Качество шрифта (на самом деле кривое разрешение)

### YotaMirror

Аналогично. Качество – как у матричных принтеров времен 90-х. Зачем рисовать картинки методом Монте-Карло? У вас 16 оттенков серого; этого более, чем достаточно. Классическая отрисовка экономичнее для батареи, красивее и четче.
Почему экономичнее? Если на светлом фоне в следующем кадре появляется объект, то вероятностная модель отрисовки (Монте-Карло) потребует как перерисовки самого объекта, так и перераспеделения точек на самом фоне: посмотрите как у вас песочные часы рисуются (на самом деле “песочное кольцо” 🙂 ). В общем избавтесь от этого кошмара, выполняйте рендеринг обычным способом. Будет гораздо красивее, будет меньше лишних вопросов, и, вдобавок – будет экономичнее.
Если кому-то нравятся эксперименты, то можно было бы сделать этот вид отрисовки дополнительной опцией.

Монте-Карло

А так получается, что вроде как разрешение экрана хорошее, но это – где-то там глубоко внутри устройства, а наблюдаем мы (пользователи) изображение очень посредственного качества.

## UPD от 27 мая 2015

Вышло обновление до 5-го андроида, но рендеринг не исправили! Когда? В общем случайно на второй экран попала капля воды. Вода, имеет тот же коэффициент преломления, что и сам матовый экран, поэтому через каплю воды стало видно все.
Вот так рендерится текст в YotaReader.

omg, 21st century…

Вот более детальные снимки рендеринга в режиме YotaMirror.

(немножко мыльная капля, чтоб лучше растекалась)

В общем все видно и без воды здесь. Весь экран в крапинку. Люди! Как вы это терпите? Почему я один возмущаюсь?

#### Как должно быть

YotaSnapshot иногда выполняет правильный рендеринг. Поэтому сделав Snapshot основного экрана, удалось увидеть “правильный” вариант для YotaMirror.

Заметьте что все гладко, и даже под каплей воды никаких “веснушек” не наблюдается.

Заключение оставлю прежним. Уважаемые разработчики YotaPhone 2, этот пост адресован в первую очередь вам. Сделайте, пожалуйста, что-нибудь. В общем-то непонятен подход. Этот пост ежедневно смотрят не меньше 50-ти человек.

С уважением,
Дятковский Степан.