четверг, 7 января 2021 г.

Emacs Lisp. Представление чисел в различных системах счисления (dec, hex, bin)

При работе с текстом мне постоянно приходится менять представление чисел, переводя из одной системы счисления в другую. Что я хотел сказать? Emacs прекрасен. Взял и накидал несколько функций на elisp. Теперь, выделив число в тексте, можно быстро представить его в другой системе. Ниже привожу листинг.

;; convert decimal to binary
(defun pa23-dec2bin (start end)
  "Convert decimal to binary."
  (interactive "r")
  (let ((var 0) (res ""))
    (setq var (string-to-number (buffer-substring-no-properties start end)))
    (while (not (= var 0))
      (setq res (concat (if (= 1 (logand var 1)) "1" "0") res))
      (setq var (lsh var -1)) )
    (if (string= res "") (setq res "0"))
    (delete-region start end)
    (insert res) ) )

;; convert decimal to hexadecimal
(defun pa23-dec2hex (start end)
  "Convert decimal to hexadecimal."
  (interactive "r")
  (let ((var 0) (res ""))
    (setq var (string-to-number (buffer-substring-no-properties start end)))
    (setq res (upcase (format "%x" var)))
    (delete-region start end)
    (insert res) ) )

;; convert hexadecimal to binary
(defun pa23-hex2bin (start end)
  "Convert hexadecimal to binary."
  (interactive "r")
  (let ((var "") (res ""))
    (setq var (string-to-number (buffer-substring-no-properties start end) 16))
    (while (not (= var 0))
      (setq res (concat (if (= 1 (logand var 1)) "1" "0") res))
      (setq var (lsh var -1)) )
    (if (string= res "") (setq res "0"))
    (delete-region start end)
    (insert res) ) )

;; convert hexadecimal to decimal
(defun pa23-hex2dec (start end)
  "Convert hexadecimal to decimal."
  (interactive "r")
  (let ((var 0) (res ""))
    (setq var (string-to-number (buffer-substring-no-properties start end) 16))
    (setq res (number-to-string var))
    (delete-region start end)
    (insert res) ) )

;; convert binary to decimal
(defun pa23-bin2dec (start end)
  "Convert binary to decimal."
  (interactive "r")
  (let ((var 0) (res ""))
    (setq var (string-to-number (buffer-substring-no-properties start end) 2))
    (setq res (number-to-string var))
    (delete-region start end)
    (insert res) ) )

;; convert binary to hexadecimal
(defun pa23-bin2hex (start end)
  "Convert binary to hexadecimal."
  (interactive "r")
  (let ((var 0) (res ""))
    (setq var (string-to-number (buffer-substring-no-properties start end) 2))
    (setq res (upcase (format "%x" var)))
    (delete-region start end)
    (insert res) ) )

вторник, 5 января 2021 г.

cmake и wxwidgets на archlinux

Так уж получается, что потянуло меня опять по ряду причин на WxWidgets. Системой моей по-прежнему является ArchLinux, а для сборки программ я предпочитаю cmake. Подготовил файлы, запускаю

cmake -G "Unix Makefiles"

и получаю сообщение об ошибке

Расследование привело меня к файлу /usr/lib/wx/config/gtk3-unicode-3.0, на который есть символическая ссылка в /usr/bin. Вот только называется файл-ссылка wx-config-gtk3, а cmake хотел просто wx-config.

Решение проблемы:

sudo ln -s /usr/lib/wx/config/gtk3-unicode-3.0 /usr/bin/wx-config

И наш 

cmake -G "Unix Makefiles"

теперь отрабатывает без ошибок.

вторник, 7 января 2020 г.

Настройка шрифтов в Arch Linux

Хотелось бы еще раз остановиться на вопросе настройки шрифтов в Arch, так как, столкнувшись с чистой установкой, которую не делал уже не знаю даже сколько лет, пришлось искать информацию для решения некоторых проблем, и это оказалось непросто.
  1. Устанавливаем желаемую версию интерпретатора freetype2 в файле /etc/profile.d/freetype2.sh. Для этого необходимо раскомментировать строку export FREETYPE... и отредактировать ее. Лично я предпочитаю версию 35 (classic mode), ибо только она дает прекрасное сглаживание шрифтов (в основном я использую шрифты семейств Dejavu и Ubuntu).
  2. Настраиваем шрифты, создавая/удаляя символические ссылки (symlinks) в /etc/fonts/conf.d на соответствующие файлы в /etc/fonts/conf.avail. Для себя я считаю необходимым добавить ссылки на следующие файлы:
    10-hinting-full.conf
    10-sub-pixel-rgb.conf
    11-lcdfilter-default.conf
  3. Настраиваем шрифты в окружении рабочего стола. Я использую xfce4, поэтому привожу снимок окна для этого DE.
  4. Если необходимо перезагрузиться, перезагружаемся и убеждаемся, что шрифты во всех приложениях выглядят идеально, просто прекрасно, за исклюнием некоторых, использующих qt5 (например, virtualbox и vlc). В следующих пунктах решаем эту проблему.
  5. Проверяем, установлен ли пакет qt5ct. Если нет, его необходимо установить.
  6. В файле /etc/profile дописываем пару строк:
    export QT_QPA_PLATFORMTHEME="qt5ct"
    export QT_AUTO_SCREEN_SCALE_FACTOR=0

    Сколько же у меня ушло времени на поиск второй строки. Весь интернет говорит только о первой (а этого мало, эффект ноль), и только установив на виртуальную машину manjaro и поковырявшись в ней, я понял что нужно.
  7. Выбираем желаемые шрифты для приложений, использующих qt5 в конфигураторе qt5ct. Достаточно просто выбрать шрифты, создавать fonts.conf не нужно.
Ну вот и все. Теперь абсолютно все программы выглядят замечательно и пользоваться системой приятно, глаза благодарны.
Вот так теперь выглядят шрифты в разных приложениях.
 
UPD 2023-04-29
 
При переходе некоторых приложений на использование библиотеки gtk4 отрисовка шрифтов у них поломалась. Шрифты выглядят размыто. Для исправления этой ситуации необходимо создать файл конфигурации ~/.config/gtk-4.0/settings.ini, в котором прописать параметры gtk-hint-font-metrics, gtk-xft-antialias, gtk-xft-hinting, gtk-xft-hintstyle и gtk-xft-rgba. Привожу содержимое моего файла.
 
[Settings]
gtk-hint-font-metrics=1
gtk-theme-name=Adwaita
gtk-icon-theme-name=elementary
gtk-font-name=DejaVu Sans ExtraLite 10
gtk-cursor-theme-name=Adwaita
gtk-cursor-theme-size=0
gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
gtk-button-images=1
gtk-menu-images=1
gtk-enable-event-sounds=0
gtk-enable-input-feedback-sounds=0
gtk-xft-antialias=1
gtk-xft-hinting=1
gtk-xft-hintstyle=hintfull
gtk-xft-rgba=none
gtk-application-prefer-dark-theme=0

воскресенье, 20 января 2019 г.

Таблично заданные функции и линейная интерполяция на C++

Время от времени в наших программах, при решении различных расчетных задач, возникает необходимость получать значения таблично заданных функций одной или двух переменных. Наиболее простым и надежным решением в данном случае является линейная интерполяция. В данной заметке я хочу привести пример определения значения таблично заданной функции двух переменных в виде реализации на C++.
В случаях, когда значения аргументов функции выходят за пределы таблицы, можно поступать по-разному: останавливать расчет и возвращать код ошибки или урезать значение аргумента до крайнего, представленного в таблице. В примере приведем первый вариант.
Стоит также учесть, что в зависимости от значений аргументов наш подход к работе с таблицей будет отличаться.
  1. Значения обоих аргументов совпадают со значениями сетки. В этом случае, не прибегая ни к каким вычислениям, мы выбираем значение функции из таблицы.
  2. Один из аргументов функции совпал со значением сетки. Тогда следует воспользоваться формулой линейной интерполяции для функции одной переменной.
  3. Ни один из аргументов функции не совпал со значениями сетки. Используем в таком случае формулы линейной интерполяции для функции двух переменных, что, собственно, не сильно отличается от работы по п.2 - то же самое, только в два захода.
Хорошо, теперь, наконец, переходим к коду. Пусть наша таблица определена несколькими векторами, содержащими значения сетки по оси X, значения сетки по оси Y и сами значения функции, то есть Z.
const vector<double> X = { 1, 1.5, 2, 2.5 };
const vector<double> Y = { 25, 30, 40 };
const vector< vector<double> > Z =
{ {0.392, 0.476, 0.574, 0.658},
  {0.406, 0.588, 0.770, 1.050},
  {0.434, 0.700, 0.980, 1.119} };
Затем приведем функции линейной интерполяции. В случае 3D, для пущей наглядности, я привожу в коде схему обозначения точек.
double linInterp2D(
    double x1,  double y1,
    double x2,  double y2,
    double x
    ) {

    double y = y1 + (x - x1) * (y2 - y1) / (x2 - x1);

    return y;
}

double linInterp3D(
    double x1,  double y1,
    double x2,  double y2,
    double z11, double z21, double z12, double z22,
    double x,   double y
    ) {

    /*

         |
      y2-| z12       z22
         |
       y-|      z
         |
      y1-| z11       z21
         |_______________
           |    |    |
           x1   x    x2

    */

    double z1 = z11 + (z12 - z11) * (y - y1) / (y2 - y1);
    double z2 = z21 + (z22 - z21) * (y - y1) / (y2 - y1);
    double z = z1 + (z2 - z1) * (x - x1) / (x2 - x1);

    return z;
}
И, наконец, нахождение значения таблично заданной функции по заданным x и y.
double findZ(double x, double y) {

    double x1 = 0; double x1i = 0;
    double y1 = 0; double y1i = 0;
    double x2 = 0; double x2i = 0;
    double y2 = 0; double y2i = 0;
    double z11 = 0;
    double z21 = 0;
    double z12 = 0;
    double z22 = 0;

    bool x_inside_range = false;
    bool y_inside_range = false;

    for (size_t i=0; i<X.size()-1; i++) {

        if ( x == X[i] ) {
            x1 = x2 = X[i];
            x1i = x2i = i;
            x_inside_range = true;
            break;
        }
        else if ( (x > X[i]) && (x < X[i+1]) ) {
            x1 = X[i];
            x1i = i;
            x2 = X[i+1];
            x2i = i+1;
            x_inside_range = true;
            break;
        }
        else if ( x == X[i+1] ) {
            x1 = x2 = X[i+1];
            x1i = x2i = i+1;
            x_inside_range = true;
            break;
        }
    }

    if ( !x_inside_range ) {
        cout << "x is outside of X axis range!\n";
        return -666;
    }

    for (size_t i=0; i<Y.size()-1; i++) {

        if ( y == Y[i] ) {
            y1 = y2 = Y[i];
            y1i = y2i = i;
            y_inside_range = true;
            break;
        }
        else if ( (y > Y[i]) && (y < Y[i+1]) ) {
            y1 = Y[i];
            y1i = i;
            y2 = Y[i+1];
            y2i = i+1;
            y_inside_range = true;
            break;
        }
        else if ( y == Y[i+1] ) {
            y1 = y2 = Y[i+1];
            y1i = y2i = i+1;
            y_inside_range = true;
            break;
        }
    }

    if ( !y_inside_range ) {
        cout << "y is outside of Y axis range!\n";
        return -666;
    }

    z11 = Z[y1i][x1i];
    z21 = Z[y1i][x2i];
    z12 = Z[y2i][x1i];
    z22 = Z[y2i][x2i];

    if ( (x1 == x2) && (y1 == y2) ) {
        return Z[y1i][x1i];
    }
    else if ( (x1 == x2) && (y1 != y2) ) {
        return linInterp2D(y1, z11, y2, z12, y);
    }
    else if ( (x1 != x2) && (y1 == y2) ) {
        return linInterp2D(x1, z11, x2, z21, x);
    }
    else {
        return linInterp3D(x1, y1, x2, y2, z11, z21, z12, z22, x, y);
    }
}
Вот и все. Вроде бы совершенно ничего сложного, но такие вот заготовочки весьма полезны, когда сроки поджимают, а некоторые функции уже написаны. Это здорово экономит время.

пятница, 10 ноября 2017 г.

ogg в mp3 без лишней возьни с мышью и окошками

До чего же мне нравится команда find. Итак, если, к примеру, у вас в машине магнитола отказывается читать правильные форматы типа ogg и требует mp3, то деваться некуда, придется ее уважить, ибо музыку в дороге послушать иногда хочется, особенно если дорога дальняя. Для конвертирования всех файлов ogg в текущем каталоге в mp3 с битрейтом, например, 320 кбит/с, можно использовать связку find и ffmpeg следующим образом:
find . -name "*.ogg" -exec ffmpeg -i {} -ab 320k {}.mp3 \;