Донецкий техникум промышленной автоматики

Упорядкування програм - що означають відмінності в порядку проходження байтів в компіляторі IBM XL Fortran

  1. Порівняння прямого і зворотного порядку байтів
  2. Малюнок 1. Подання прямого і зворотного порядку байтів в пам'яті
  3. Порядок проходження елементів вектора і порядок проходження байтів елемента вектора
  4. Малюнок 2. Подання прямого порядку проходження елементів вектора в векторних регістрах
  5. Малюнок 3. Подання зворотного порядку проходження елементів вектора в векторних регістрах
  6. Нові вбудовані процедури завантаження та вивантаження векторів
  7. Виклик C-функцій зі змінною кількістю аргументів з Fortran
  8. Зв'язок по пам'яті між елементами різного розміру
  9. EQUIVALENCE
  10. COMMON-блоки
  11. Оператори ENTRY
  12. зв'язок аргументів
  13. Керований форматом введення / виведення
  14. 16-байтниє речові і комплексні типи
  15. Змінні середовища для перетворення під час виконання
  16. Специфікатор CONVERT = в операторі OPEN
  17. Директиви вихідного коду
  18. Параметр компілятора -qufmt
  19. Завантаження і вивантаження в протилежному порядку байтів
  20. Ресурси для скачування

При міграції з компілятора, що використовує прямий порядок байтів, на компілятор з зворотним порядком байтів можуть знадобитися деякі зміни вихідного коду для збереження первісного поведінки програми або результатів її роботи. Вектори, зв'язок по пам'яті між елементами різного розміру, 16-байтниє речові числа, комплексні числа і неформатовані файли даних - це ті аспекти вихідного коду, на які слід звернути увагу при портировании такого роду. Дистрибутиви Linux® зі зворотним порядком байтів на IBM Power Systems ™ і дистрибутиви з прямим порядком використовують різні ABI. Програми, які мають залежності зі старим ABI, необхідно оновити. У тому, що стосується порядку байтів в векторах, нові вбудовані процедури полегшують портирование.

У даній статті розглядаються проблеми, які можуть виникати при портировании Fortran-коду з прямим порядком байтів в код на протилежне на IBM XL Fortran для Power Systems. Також наводяться рекомендації щодо зміни написання коду і описуються можливості та параметри компілятора, що полегшують портирование коду.

Порівняння прямого і зворотного порядку байтів

Порядок байтів визначає спосіб інтерпретації даних в пам'яті. Порядок байтів, який використовується платформою, залежить від архітектури процесора. Сьогодні найбільш широко застосовуються два види черговості проходження байтів: прямий порядок і зворотний порядок.

На платформах з прямим порядком проходження байтів ( "big endian") байти в пам'яті розташовуються так, що першим ( "лівим") є старший байт. На платформах зі зворотним порядком проходження байтів ( "little endian") першим ( "лівим") є молодший байт.

Наприклад, на малюнку 1 зображений формат зберігання числа 000102030405060716 (що розглядається як 8-байтное ціле) в пам'яті на платформах з прямим і зворотним порядком байтів. На цьому малюнку a є адреса комірки пам'яті.

Малюнок 1. Подання прямого і зворотного порядку байтів в пам'яті
При міграції з компілятора, що використовує прямий порядок байтів, на компілятор з зворотним порядком байтів можуть знадобитися деякі зміни вихідного коду для збереження первісного поведінки програми або результатів її роботи

вектори

Архітектура процесора IBM POWER® підтримує 16-байтниє вектори, що містять шістнадцять 1-байтних елементів, вісім 2-байтних, чотири 4-байтних або два 8-байтних елемента. Процесор має 128-бітові векторні регістри і підтримує інструкції для завантаження векторів в регістри, операцій з векторами в регістрах і вивантаження векторних регістрів в оперативну пам'ять. Компілятори IBM XL підтримують вбудовані процедури для роботи з векторами на рівні мови програмування.

Порядок проходження елементів векторів в платформах з прямим і зворотним порядком байтів різний. Для полегшення обліку цих відмінностей представлені нові параметри компілятора і вбудовані процедури. У наступних розділах розглядаються ці відмінності і нові функціональні можливості.

Порядок проходження елементів вектора і порядок проходження байтів елемента вектора

Існує два способи розміщення елементів вектора в векторному регістрі. Можна завантажити елементи, починаючи з молодшого і закінчуючи самим старшим, так, щоб елемент 0 був у векторному регістрі самим лівим елементом. Інший спосіб - завантажити елементи, починаючи з найстаршого і закінчуючи наймолодшою, так щоб елемент 0 був у векторному регістрі самим правим елементом. Перше розташування називається прямим порядком проходження елементів вектора, друге - зворотним.

При прямому порядку байтів завжди використовується прямий порядок елементів вектора.

При зворотному порядку байтів можна вибрати один з двох варіантів: прямий порядок елементів вектора і зворотний порядок елементів вектора.

Незалежно від порядку проходження елементів вектора, елементи вектора при прямому порядку використовують в пам'яті прямий порядок байтів. Елементи вектора при зворотному порядку за замовчуванням використовують зворотний порядок байтів в пам'яті.

На малюнках 2 і 3 показана різниця між прямим і зворотним порядком проходження елементів вектора.

На малюнку 2 зображено уявлення 16-байтного вектора 000102030405060708090A0B0C0D0E0F16 в векторному регістрі при прямому порядку проходження байтів. Позначення b 127 і b 0 на малюнку відзначають 127-й і 0-й біт регістра відповідно. На малюнку показані вистави векторів, заповнених елементами довжиною 1, 2, 4 і 8 байтів відповідно зверху вниз.

Малюнок 2. Подання прямого порядку проходження елементів вектора в векторних регістрах

На малюнку 3 зображено уявлення 16-байтного вектора 000102030405060708090A0B0C0D0E0F16 в векторному регістрі при зворотному порядку проходження байтів. Позначення b 127 і b 0 на малюнку відзначають 127-й і 0-й біт регістра відповідно. На малюнку показані вистави векторів, заповнених елементами довжиною 1, 2, 4 і 8 байтів відповідно зверху вниз.

Малюнок 3. Подання зворотного порядку проходження елементів вектора в векторних регістрах

параметр -qaltivec

Параметр -qaltivec дозволяє вказати компілятору, що використовує зворотний порядок байтів, в якому порядку розміщувати елементи вектора в векторних регістрах.

При вказівці -qaltivec = le компілятор завантажує вектори в зворотному порядку елементів і передбачає, що вектори завантажуються на зберігання на протилежне елементів. При необхідності компілятор вставляє операції перестановки вектора, щоб гарантувати використання вбудованими процедурами load і store зворотного порядку елементів. Для вбудованих процедур роботи з векторами, що звертаються до конкретних елементів, компілятор припускає, що вектори були завантажені на протилежне елементів. При зворотному порядку байтів параметр -qaltivec = le використовується за умовчанням.

При вказівці -qaltivec = be компілятор завантажує вектори в прямому порядку елементів і передбачає, що вектори завантажуються на зберігання з прямим порядком елементів. При необхідності компілятор вставляє операції перестановки вектора, щоб гарантувати використання вбудованими процедурами load і store прямого порядку елементів. Для вбудованих процедур роботи з векторами, що звертаються до конкретних елементів, компілятор припускає, що вектори були завантажені з прямим порядком елементів.

Для демонстрації вищесказаного розглянемо наступну програму:

program main vector (integer (8)) v integer (8) i (2) equivalence (v, i) i = [z'0001020304050607 ', z'08090A0B0C0D0E0F'] print 1, "First vector element:", vec_extract (v , 0) print 1, "Second vector element:", vec_extract (v, 1) 1 format (A, z16.16) end program

Якщо ця програма компілюється на платформі з прямим порядком байтів або на платформі на протилежне байт з використанням параметра -qaltivec = le, виводиться наступна інформація:

First vector element: 0001020304050607 Second vector element: 08090A0B0C0D0E0F

Якщо програма компілюється на платформі зі зворотним порядком байтів з використанням параметра -qaltivec = be, виводиться наступна інформація:

First vector element: 08090A0B0C0D0E0F Second vector element: 0001020304050607

Вектор був завантажений в векторний регістр навпаки, хоча порядок елементів в масиві i не змінився.

Більш стерпним способом роботи з векторами є їх завантаження і вивантаження з використанням розглянутих в наступному розділі вбудованих процедур vec_xl, vec_xl_be, vec_xst і vec_xst_be замість EQUIVALENCE. Розглянемо наступну програму:

vector (real (4)) v1, v2, v3, v4 real (4) a (4) v1 = vec_xl (0, [real (4) :: 1.0, 2.0, 3.0, 4.0]) call vec_xst (v1, 0 , a) print *, 'v1 =', a v2 = vec_neg (v1) call vec_xst (v2, 0, a) print *, 'v2 =', a! Об'єднати старший і молодший в залежності від порядку елементів вектора v3 = vec_mergeh (v1, v2) call vec_xst (v3, 0, a) print *, 'v3 =', a v4 = vec_mergel (v1, v2) call vec_xst (v4, 0 , a) print *, 'v4 =', a end

Виведені результати однакові на обох платформах (і з прямим, і з зворотним порядком байтів). Виводиться наступна інформація:

v1 = 1.000000000 2.000000000 3.000000000 4.000000000 v2 = -1.000000000 -2.000000000 -3.000000000 -4.000000000 v3 = 1.000000000 -1.000000000 2.000000000 -2.000000000 v4 = 3.000000000 -3.000000000 4.000000000 -4.000000000


Вбудовані векторні процедури vec_xl, vec_xst, vec_mergeh і vec_mergel враховують порядок елементів вектора. Іншими словами, при компіляції програми на платформі зі зворотним порядком байтів і з параметром -qaltivec = le:

  • vec_xl використовує інструкцію Vector Scalar eXtension (VSX) load, яка завжди завантажує вектори з прямим порядком елементів. Потім використовується інструкція перестановки вектора, що перевертає вектор в регістрі відповідно до прийнятого зворотним порядком елементів.
  • vec_xst передбачає, що вектор в регістрі використовує зворотний порядок елементів, тому використовується інструкція перестановки для перетворення в прямий порядок елементів вектора. Потім використовується інструкція VSX store, завжди виконує вивантаження вектора в пам'ять в прямому порядку елементів.
  • vec_mergeh знає, що елементи вектора починаються справа. Регістри вектора, що містять v1 і v2, виглядають наступним чином:

v1 4.0 3.0 2.0 1.0 v2 -4.0 -3.0 -2.0 -1.0

Оскільки vec_mergeh починає вважати справа, вона коректно використовує значення 1.0 і 2.0 для елементів 0 і 2 при виконанні vec_mergeh (v1, v2).

  • Аналогічно, vec_mergel знає, що елементи вектора починаються справа. Отже, вона коректно використовує значення -1.0 і -2.0 для елементів 1 і 3 при виконанні vec_mergel (v1, v2).

При компіляції програми на платформі з прямим порядком байтів або при компіляції її на платформі зі зворотним порядком байтів і з параметром - -qaltivec = be:

  • vec_xl використовує інструкцію VSX load, яка завжди завантажує вектори з прямим порядком елементів. Немає необхідності вставляти інструкцію перестановки вектора.
  • vec_xst передбачає, що вектор в регістрі використовує прямий порядок елементів. Тобто вона безпосередньо використовує інструкцію VSX store, завжди виконує вивантаження вектора в пам'ять в прямому порядку елементів.
  • vec_mergeh знає, що елементи вектора починаються зліва. Регістри вектора, що містять v1 і v2, виглядають наступним чином:

v1 1.0 2.0 3.0 4.0 v2 -1.0 -2.0 -3.0 -4.0

Оскільки vec_mergeh починає вважати зліва, вона коректно використовує значення 1.0 і 2.0 для елементів 0 і 2 при виконанні vec_mergeh (v1, v2).

Аналогічно, vec_mergel знає, що елементи вектора починаються зліва. Отже, вона коректно використовує значення -1.0 і -2.0 для елементів 1 і 3 при виконанні vec_mergel (v1, v2).

Для програм, які не використовують EQUIVALENCE, параметр -qaltivec = be може бути корисний при портировании коду з прямого порядку байтів в зворотний.

Криптографічні вбудовані процедури POWER8 вимагають, щоб вхідні вектори використовували прямий порядок елементів вектора. Це можна зробити або за допомогою параметра -qaltivec = be, або за допомогою вбудованих процедур vec_xl_be і vec_xst_be для завантаження і вивантаження. Ці функції завантаження і вивантаження векторів розглядаються в наступному розділі.

Нові вбудовані процедури завантаження та вивантаження векторів

Були додані нові вбудовані процедури завантаження та вивантаження векторів, що використовують VSX-інструкції. Інформація по цим вбудованим процедурам приведена в Довіднику по компілятору XL Fortran ( бібліотека документації по XL Fortran для Linux ).

VEC_XL (ARG1, ARG2)
Ця функція завантажує 16-байтний вектор з адреси оперативної пам'яті, зазначеного зміщенням ARG1 і адресою ARG2, з відповідним порядком елементів для використовуваної платформи і параметром -qaltivec.

ARG1 - це INTENT (IN), тип integer.

ARG2 - це INTENT (IN) будь-якого з наступних типів:

  • REAL (4) або REAL (8)
  • INTEGER (1), INTEGER (2), INTEGER (4) або INTEGER (8)
  • VECTOR

VEC_XL_BE (ARG1, ARG2)
Ця функція завантажує 16-байтний вектор з адреси оперативної пам'яті, зазначеного зміщенням ARG1 і адресою ARG2, з прямим порядком незалежно від платформи або параметра -qaltivec.

ARG1 - це INTENT (IN), тип integer.

ARG2 - це INTENT (IN) будь-якого з наступних типів:

  • REAL (4) або REAL (8)
  • INTEGER (1), INTEGER (2), INTEGER (4) або INTEGER (8)
  • VECTOR

VEC_XST (ARG1, ARG2, ARG3)
Ця функція вивантажує елементи 16-байтного вектора, зазначеного аргументом ARG1, в даний адреса пам'яті. Адреса обчислюється шляхом додавання значення зсуву, зазначеного в ARG2, до адресою пам'яті, вказаною в ARG3, з відповідним порядком елементів для використовуваної платформи і параметром -qaltivec.

ARG1 - це INTENT (IN), вектор.

ARG2 - це INTENT (IN), тип integer.

ARG3 - це INTENT (OUT), який повинен бути вектором або мати тип integer або real:

  • Якщо ARG3 є вектором, він повинен мати такий же тип, що і ARG1.
  • Якщо ARG3 не є вектором, а ARG1 є вектором з типом integer або типом unsigned, ARG3 повинен мати тип INTEGER з параметром такого ж типу, що й елементи ARG1.
  • Якщо ARG3 не є вектором, а ARG1 є вектором з типом real, ARG3 повинен мати такий же тип, що і елементи ARG1.
  • Якщо ARG3 не є вектором, а ARG1 є вектором з типом pixel, ARG3 повинен мати тип INTEGER (2).

VEC_XST_BE (ARG1, ARG2, ARG3)
Ця функція вивантажує елементи 16-байтного вектора, зазначеного аргументом ARG1, в даний адреса пам'яті. Адреса обчислюється шляхом додавання значення зсуву, зазначеного в ARG2, до адресою пам'яті, вказаною в ARG3, з прямим порядком елементів незалежно від використовуваної платформи і параметра -qaltivec.

ARG1 - це INTENT (IN), вектор.

ARG2 - це INTENT (IN), тип integer.

ARG3 - це INTENT (OUT), який повинен бути вектором або мати тип integer або real:

  • Якщо ARG3 є вектором, він повинен мати такий же тип, що і ARG1.
  • Якщо ARG3 не є вектором, а ARG1 є вектором з типом integer або типом unsigned, ARG3 повинен мати тип INTEGER з параметром такого ж типу, що й елементи ARG1.
  • Якщо ARG3 не є вектором, а ARG1 є вектором з типом real, ARG3 повинен мати такий же тип, що і елементи ARG1.
  • Якщо ARG3 не є вектором, а ARG1 є вектором з типом pixel, ARG3 повинен мати тип INTEGER (2).

XL Fortran для Linux on Power Systems зі зворотним порядком байтів використовує нову специфікацію IBM Power Architecture® 64-bit ELF V2 ABI . Цей новий ABI покращує кілька аспектів, в тому числі виклики функцій. Однак це означає, що компонувальні файли, розроблені для старого ABI, необхідно перенести на новий ABI. Програми на Fortran, C і C ++, які дотримуються стандартів відповідної мови, не вимагають портирования на новий ABI. Програми, які містять нестандартні розширення, необхідно проаналізувати на чутливість до ABI. Одним із прикладів в Fortran є виклик C-функцій зі змінною кількістю аргументів.

Виклик C-функцій зі змінною кількістю аргументів з Fortran

Мова C дозволяє використовувати функції зі змінним кількістю аргументів. Для них використовується три крапки (...). Наприклад, printf має наступний C-прототип:

int printf (const char * restrict format, ...);

При виклику функцій зі змінною кількістю аргументів ELF V2 ABI вимагає настройки в стеці галузі збереження параметрів. Тому виклики функцій зі змінною кількістю аргументів повинні мати точні прототипи.

Однак стандарт мови Fortran вважає C-функції зі змінним кількістю аргументів несумісними і не надає способу вказівки інтерфейсів для них. У деяких програмах робляться спроби подолати це обмеження шляхом додавання явного інтерфейсу, що містить максимальну кількість аргументів, яке планується використовувати. наприклад:

interface function printf1int (format, a) bind (c, name = 'printf') use, intrinsic :: iso_c_binding, only: c_int implicit none integer (c_int) printf1int character, intent (in) :: format (*) integer (c_int ), value :: a end function end interface

Виклик printf1int з використанням наведеного вище інтерфейсу з новим ABI може привести до пошкодження стека через відсутність збереження архітектурної спадщини параметрів. Щоб повідомити компілятор XL Fortran про використання змінної кількості аргументів, додайте в інтерфейс директиву procedure_attribute (varargs).

interface function printf1int (format, a) bind (c, name = 'printf') use, intrinsic :: iso_c_binding, only: c_int implicit none integer (c_int) printf1int character, intent (in) :: format (*) integer (c_int ), value :: a! ibm * procedure_attribute (varargs) end function end interface

Зв'язок по пам'яті між елементами різного розміру

При портировании програми з прямим порядком байтів на платформу зі зворотним порядком байтів необхідно враховувати зв'язок по пам'яті між елементами різного типу. У Fortran це відноситься до EQUIVALENCE, COMMON-блокам, операторам ENTRY, зв'язку аргументів і керованого форматом вводу / виводу. Ці елементи докладно розглядаються в наступних розділах.

Зверніть увагу, що шістнадцяткові значення завжди виводяться з прямим порядком байтів.

EQUIVALENCE

Стандарт Fortran обмежує типи об'єктів, які можна пов'язувати з пам'яті за допомогою оператора EQUIVALENCE. Однак XL Fortran (і більшість компіляторів) допускає появу в EQUIVALENCE об'єктів практично будь-якого типу. При використанні EQUIVALENCE з елементами різного розміру результати можуть відрізнятися для прямого і зворотного порядку байтів. Для демонстрації цього розглянемо наступну програму:

integer (8) j integer (4) i (2) integer (2) h (4) integer (1) k (8) equivalence (j, i), (j, h), (j, k) j = z '0001020304050607' print 1, 'j =', j print 2, 'i =', i print 4, 'h =', h print 8, 'k =', k 1 format (A, "z '", z16 .16, " '") 2 format (A, 2 ( "z'", z8.8, " '", 1x)) 4 format (A, 4 ( "z'", z4.4, " '", 1x)) 8 format (A, 8 ( "z '", z2.2, "'", 1x)) end

У цій програмі зазначено, що j використовує область пам'яті спільно з i, h і k - при цьому всі вони мають різний тип. І для прямого порядку байтів, і для зворотного масиви розташовуються зліва направо, а якщо точніше - наймолодший елемент масиву має найменший адресу в оперативній пам'яті. Порядок байтів кожного елемента масиву різний для прямого і зворотного порядку байтів. При прямому порядку старший байт кожного елемента масиву знаходиться зліва, тобто j, i, h і k в пам'яті виглядають однаково. Виводиться наступна інформація:

j = z'0001020304050607 'i = z'00010203' z'04050607 'h = z'0001' z'0203 'z'0405' z'0607 'k = z'00' z'01 'z'02' z ' 03 'z'04' z'05 'z'06' z'07 '

На платформах з прямим порядком молодший байт кожного елемента масиву знаходиться зліва, і, отже, j, i, h і k в пам'яті виглядають по-різному. Виводиться наступна інформація:

j = z'0001020304050607 'i = z'04050607' z'00010203 'h = z'0607' z'0405 'z'0203' z'0001 'k = z'07' z'06 'z'05' z ' 04 'z'03' z'02 'z'01' z'00 '

COMMON-блоки

COMMON-блоки забезпечують зв'язок по пам'яті між елементами в різних модулях компіляції. Якщо один і той же блок в двох модулях компіляції оголошений по-різному, члени COMMON-блоку зв'язуються по пам'яті. Якщо відповідні елементи мають різні розміри, на них необхідно звернути особливу увагу при портировании коду з прямого порядку байтів на зворотний. Розглянемо наступну програму:

subroutine sub1 integer (8) j common / blk / jj = z'0001020304050607 'print 1,' sub1: ', j 1 format (A, "z'", z16.16, " '") end subroutine subroutine sub2 integer ( 4) i (2) common / blk / i print 2, 'sub2:', i 2 format (A, 2 ( "z '", z8.8, "'", 1x)) end subroutine program main call sub1 call sub2 end program

У наведеній вище програмі j і i спільно використовують область зберігання і мають різні типи. Результат роботи програми показує, що елементи i упорядковуються по-різному для прямого і зворотного порядку байтів. При прямому порядку виконання програми призводить до наступних результатів:

sub1: z'0001020304050607 'sub2: z'00010203' z'04050607 '

При зворотному порядку виконання програми призводить до наступних результатів:

sub1: z'0001020304050607 'sub2: z'04050607' z'00010203 '

Оператори ENTRY

Зв'язок по пам'яті між результатами функцій і їх операторами ENTRY виникає в разі різних властивостей результатів. У наступній програмі f і g пов'язані з пам'яті.

function f (a) double precision a, f real g entry g (a) f = a end function program main interface function f (a) double precision a, f end function function g (a) double precision a real g end function end interface double precision xx = z'0001020304050607 'print' (z16.16) ', f (x) print' (z8.8) ', g (x) end program

При прямому порядку байтів g, що має тип real з одинарної точністю, пов'язана з пам'яті зі старшою половиною змінної f подвійної точності. Результат роботи програми при прямому порядку байтів:

0001020304050607 00010203

При зворотному порядку байтів g виявляється пов'язана з пам'яті з молодшою ​​половиною f. Результат роботи програми при зворотному порядку байтів:

0001020304050607 04050607

зв'язок аргументів

Виклики в стилі FORTRAN 77 не використовують явних інтерфейсів і припускають, що за передачею коректних типів стежить користувач. При прямому порядку байтів деякі невідповідні вимогам програми можуть працювати успішно, незважаючи на невідповідність фактичних і формальних аргументів. Розглянемо наступну програму:

program main integer :: i = 1 character (5) :: c = 'abcd' integer (2) :: h = 2 real (8) :: d = 1.0 call hexprint (i, 4) call hexprint (c, 5 ) call hexprint (h, 2) call hexprint (d, 8) end program subroutine hexprint (buffer, size) character (8) buffer integer size print 100, buffer (1: size) 100 format (z <2 * size>. <2 * size>) end subroutine

Програма не відповідає вимогам, так як пов'язує фактичні аргументи різних типів integer з формальним аргументом символьного типу. Програма не використовує явний інтерфейс і, отже, компілятор не знаходить помилки. При прямому порядку символьні і несімвольние дані використовують один і той же порядок байтів, і, отже, програма виведе очікувані результати. При зворотному порядку байтів цього не відбувається. Для демонстрації розглянемо результати роботи програми при прямому і зворотному порядку байтів.

При прямому порядку програма виводить наступні результати:

00000001 6162636420 0002 3FF0000000000000

При зворотному порядку програма виводить наступні результати:

01000000 6162636420 0200 000000000000F03F

Керований форматом введення / виведення

У керованих форматом операціях введення / виведення дескриптор редагування (edit descriptor), який використовується для читання або запису елемента вводу / виводу, повинен відповідати типу і параметрам типу цього елемента. Наприклад, можуть виникати проблеми портування, якщо дескриптор редагування A, що передбачає символьний тип елемента вводу / виводу, використовується для читання або запису елемента, що має тип integer. Наприклад, розглянемо наступну програму:

character (4) file integer (4) aa = z'61626364 'write (file,' (A) ') a print *, file end

При прямому порядку байтів вона виводить наступну інформацію:
abcd

Але при зворотному порядку байтів вона виводить наступну інформацію:
dcba

16-байтниє речові і комплексні типи

У XL Fortran тип з плаваючою комою підвищеної точності (extended-precision floating-point), REAL (16), не є 128-бітовим форматом, введеним в IEEE-стандарті (Institute of Electrical and Electronics Engineers). Замість цього REAL (16) складається з двох REAL (8) -Части з різними масштабами, які не перетинаються (за винятком нульових або близьких до нуля значень). Значення старшого REAL (8), яке в пам'яті йде першим, повинно мати велику величину, навіть при зворотному порядку байтів. Значення числа REAL (16) є сумою двох його REAL (8) -Части.

Комплексні числа складаються з дійсної та уявної частин, причому дійсна частина завжди йде до уявної.

Розглянемо наступний фрагмент коду:

real (8) d (2) real (16) q complex (8) z equivalence (q, d), (q, z) q = 1.0q0

І при прямому, і при зворотному порядку байтів першим елементом d є 1.0d0, а другим - 0.0d0. Дійсною частиною комплексного числа z є 1.0d0, а уявної - 0.0d0.

Порядок проходження байтів елементів 16-байтних речових і комплексних чисел різниться для прямого і зворотного порядку байтів, але порядок елементів однаковий.

Неформатовані файли даних Fortran складаються із записів і маркерів записів (record marker). Маркери записів - це 4- або 8-байтниє цілі, що містять кількість байтів в запису. Маркери записів розташовані до і після кожного запису. Розглянемо наступний приклад

write (10) 10, 11 end

Ця програма записує наступні дані (в двійковому вигляді) в файл, підключений до модуля 10:

0x00000008 0x0000000a 0x0000000b 0x00000008

Оскільки маркери записів є цілими числами, вони залежать від порядку байтів. Також, оскільки числа 10 і 11, які використовуються в прикладі, є цілими, вони теж залежать від порядку байтів. В результаті неформатований файл даних, який використовує один порядок байтів (наприклад, прямий), не може бути прочитаний на платформі з іншим порядком байтів без перетворення. XL Fortran надає кілька методів конвертування валюти. Ось вони в порядку зменшення пріоритету:

  • Параметри системи часу виконання XLFRTEOPTS = ufmt_bigendian = <модулі> і XLFRTEOPTS = ufmt_littleendian = <модулі>.
  • Специфікатор CONVERT = в операторі OPEN.
  • Директива @PROCESS UFMT.
  • Параметр компілятора -qufmt.

Ці методи докладно описані в наступних розділах.

Змінні середовища для перетворення під час виконання

Для вказівки порядку байтів в неформатованих файлах даних при перетворенні під час виконання можна використовувати змінні середовища XLFRTEOPTS = xlf_bigendian = <модулі> і XLFRTEOPTS = xlf_littleendian = <модулі>.

Мінлива XLFRTEOPTS = xlf_bigendian = <модулі> допустиме лише при зворотному порядку байтів для модулів, підключених до неформатований файлів даних з прямим порядком байтів.

Мінлива XLFRTEOPTS = xlf_littleendian = <модулі> допустима при прямому порядку байтів для модулів, підключених до неформатований файлів даних зі зворотним порядком байтів.

Прикладами коректних значень параметра <модулі> для xlf_bigendian і xlf_littleendian (в наступному прикладі показаний випадок xlf_bigendian, але це значення може бути застосовано також і для xlf_bigendian) є:

XLFRTEOPTS = xlf_bigendian = 5
Вказує, що модуль 5 підключений до файлу з прямим порядком байтів.
XLFRTEOPTS = xlf_bigendian = 5-10
Вказує, що модулі з 5 по 10 підключені до файлів з прямим порядком байтів.
XLFRTEOPTS = xlf_bigendian = 1,5-10
Вказує, що модулі 1 і з 5 по 10 підключені до файлів з прямим порядком байтів.
XLFRTEOPTS = xlf_bigendian = 1
Вказує, що всі модулі, починаючи з 1, підключені до файлів з прямим порядком байтів.
XLFRTEOPTS = xlf_bigendian = newunit
Вказує, що все автоматично згенерували модулі підключені до файлів з прямим порядком байтів. Автоматично згенеровані неформатовані модулі створюються з негативними ідентифікаторами.
XLFRTEOPTS = xlf_bigendian = 1, newunit або XLFRTEOPTS = xlf_bigendian = *
Вказує, що всі модулі підключені до файлів з прямим порядком байтів.

Специфікатор CONVERT = в операторі OPEN

За допомогою специфікатор CONVERT = можна вказати порядок проходження байтів в неформатованих файлах даних для перетворення. Допустимими значеннями для даного специфікатор є:

CONVERT = 'NATIVE'
Вказує компілятору, що порядок проходження байтів у файлі ідентичний використовуваному платформою і в перетворенні немає необхідності. Це значення за замовчуванням.

CONVERT = 'BIG_ENDIAN'
Вказує компілятору, що неформатований файл використовує прямий порядок байтів. На платформах зі зворотним порядком байтів виконується перетворення під час операцій передачі даних в файл і з нього. На платформах з прямим порядком байтів ніяких перетворень не виконується.

CONVERT = 'LITTLE_ENDIAN'
Вказує компілятору, що неформатований файл використовує зворотний порядок байтів. На платформах з прямим порядком байтів виконується перетворення під час операцій передачі даних в файл і з нього. На платформах зі зворотним порядком байтів ніякі перетворення не виконуються.

Директиви вихідного коду

Директиви вихідного коду @PROCESS UFMT застосовуються до всіх операторам OPEN в модулі компіляції, перед яким вони розташовані.

@PROCESS UFMT (big endian)
Вказує, що оператори OPEN підключаються до файлів даних з прямим порядком байтів. На платформах зі зворотним порядком байтів виконується перетворення під час операцій передачі даних в файл і з нього. На платформах з прямим порядком байтів ніякі перетворення не виконуються.

@PROCESS UFMT (little endian)
Вказує, що оператори OPEN підключаються до файлів даних зі зворотним порядком байтів. На платформах з прямим порядком байтів виконується перетворення під час операцій передачі даних в файл і з нього. На платформах зі зворотним порядком байтів ніякі перетворення не виконуються.

Параметр компілятора -qufmt

За допомогою параметра компілятора -qufmt можна вказати під час компіляції порядок проходження байтів в неформатованих файлах даних для перетворення.

-qufmt = be
Повідомляє компілятору, що всі неформатовані файли даних використовують прямий порядок байтів. На платформах зі зворотним порядком байтів виконується перетворення під час операцій передачі даних в файл і з нього. На платформах з прямим порядком байтів ніякі перетворення не виконуються.

-qufmt = le
Повідомляє компілятору, що всі неформатовані файли даних використовують зворотний порядок байтів. На платформах з прямим порядком байтів виконується перетворення під час операцій передачі даних в файл і з нього. На платформах зі зворотним порядком байтів ніякі перетворення не виконуються.

Завантаження і вивантаження в протилежному порядку байтів

XL Fortran надає наступні вбудовані процедури для перетворення порядку проходження байтів:

LOAD2R (X)
Завантажує значення X з протилежним порядком байтів, де X - формальний аргумент INTENT (IN) з типом INTEGER (2). Результат має тип INTEGER (2).

LOAD4R (X)
Завантажує значення X з протилежним порядком байтів, де X - формальний аргумент INTENT (IN) з типом INTEGER (4). Результат має тип INTEGER (4).

LOAD8R (X)
Завантажує значення X з протилежним порядком байтів, де X - формальний аргумент INTENT (IN) з типом INTEGER (8). Результат має тип INTEGER (8).

REVERSE_BYTE_ORDER (X)
Універсальна, ініціюється автоматично значення X з протилежним порядком байтів, де X - формальний аргумент INTENT (IN) з типом INTEGER (2), INTEGER (4) або INTEGER (8). Вона дозволяється в функції LOAD2R, LOAD4R або LOAD8R в залежності від типу X. Результат має такий же тип і параметри типу, що і X.

VEC_REVB (ARG1)
Повертає вектор такого ж типу, що й ARG1, що містить байти відповідних елементів ARG1 в протилежному порядку. ARG1 - це вектор INTENT (IN) з типом integer, unsigned або real.

VEC_REVE (ARG1)
Повертає вектор такого ж типу, що й ARG1, що містить елементи ARG1 в протилежному порядку. ARG1 - це вектор INTENT (IN) з типом integer, unsigned або real. Повертає вектор з таким же типом, що і X, що містить вектор INTENT (IN) з типом integer, unsigned або real.

Ресурси для скачування

Схожі тими

Підпішіть мене на ПОВІДОМЛЕННЯ до коментарів