Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 арифметика в FPC - cast Integer to Int64  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2609
Столкнулся с проблемой (видимо из-за незнания/непонимания).

FPC 3.0.0
компилю с ключами -TWin32 -Mobjfpc

Есть такая функция:
function MakeFullNumber( nSerial, nNumber: Integer ): Int64;
begin
  Result := Int64( nSerial ) * $FFFFFFFF + nNumber;
end;  


На делфи
ShowMessage( IntToStr( MakeFullNumber( 200210, 1 ) ) );

выдает "859895402131951" - это правильно, калькулятор подтверждает.

FPC же упорно выдает какое-то странное число "-859886812597777", даже если сделать
Result := Int64( Int64( Int64( nSerial ) * Int64( $FFFFFFFF ) ) + Int64( nNumber ) );


Единственное, что помогает, это переделать функцию так:
function MakeFullNumber( nSerial, nNumber: Int64 ): Int64;
begin
  Result := nSerial * $FFFFFFFF + nNumber;
end;    

тогда результат совпадает, но это не вариант - функция экспортится из библиотеки, которую используют.
Пока что нашел только такое г-решение проблемы:
function MakeFullNumber( nSerial, nNumber: Integer ): Int64;
var
  nSerial64, nNumber64: Int64;
begin
  nSerial64 := nSerial;
  nNumber64 := nNumber;
  Result := nSerial64 * $FFFFFFFF + nNumber64;
end;

Так тоже, естественно, правильно работает и я пока остановился на этом.

Но может кто подскажет - может есть какая-то настройка/деректива, которая включает кастинг "как в Делфи"? Я не нашел пока. И если кто объяснит такое поведение - тоже спасибо.
19 июн 17, 17:08    [20575472]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 44070

YuRock
Но может кто подскажет - может есть какая-то настройка/деректива, которая включает кастинг
"как в Делфи"?

-Mdelphi ?..

Posted via ActualForum NNTP Server 1.5

19 июн 17, 17:33    [20575567]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 2754
YuRock
И если кто объяснит такое поведение - тоже спасибо.

Похоже на баг компилятора. FPC 3.1.1, из транка, под Linux x64 выдаёт корректный результат, под Win32 вообще -200209.
19 июн 17, 17:39    [20575595]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2609
Dimitry Sibiryakov,

Нет, не помогает. Ведет себя так же, как и -Mobjfpc
19 июн 17, 17:52    [20575655]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2609
Kazantsev Alexey
под Linux x64 выдаёт корректный результат, под Win32 вообще -200209

Под win64 та же история.
19 июн 17, 17:54    [20575667]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9990
YuRock, Похоже на то, что при касте в старших разрядах оказывается мусор. Попробуй так

Result := (Int64(nSerial) and $FFFFFFFF) * $FFFFFFFF +( Int64(nNumber)  and $FFFFFFFF);
19 июн 17, 21:02    [20576002]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
SimplTsar
Member

Откуда:
Сообщений: 39
YuRock
... если кто объяснит такое поведение - тоже спасибо.


function MakeFullNumber( nSerial, nNumber: Int64 ): Int64;
begin
  Result := nSerial;
  Result := Result * $FFFFFFFF + nNumber;
end;    


Проверено FPC 3.0.2, Lazarus 1.6.4

Скорее всего "виновата" оптимизация при преобразовании типов. Достаточно посмотреть формируемый код ассембера в различных реализациях функций.
19 июн 17, 21:34    [20576049]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
SimplTsar
Member

Откуда:
Сообщений: 39
Описался
вместо
 function MakeFullNumber( nSerial, nNumber: Int64 ): Int64;

должно быть
 function MakeFullNumber( nSerial, nNumber: Integer ): Int64;
19 июн 17, 21:39    [20576051]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2609
_Vasilisk_
YuRock, Похоже на то, что при касте в старших разрядах оказывается мусор. Попробуй так

Result := (Int64(nSerial) and $FFFFFFFF) * $FFFFFFFF +( Int64(nNumber)  and $FFFFFFFF);

Да, так и есть. С принудительным обнулением старших разрядов выдает верный результат.
Страшненькая особенность, которую придется учитывать при желании перевести какой-нибудь проект на fpc.
20 июн 17, 13:00    [20577146]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2609
SimplTsar
Скорее всего "виновата" оптимизация при преобразовании типов. Достаточно посмотреть формируемый код ассембера в различных реализациях функций.

Мне не достаточно :) - я в ассемблере ~0. А причину проблемы определил уже _Vasilisk_.
20 июн 17, 13:01    [20577150]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
lazarus bugtracker
Guest
YuRock
Страшненькая особенность, которую придется учитывать при желании перевести какой-нибудь проект на fpc.

https://bugs.freepascal.org/view_all_bug_page.php
Избавите многих от страшненького.
20 июн 17, 14:26    [20577562]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9990
YuRock
Страшненькая особенность, которую придется учитывать при желании перевести какой-нибудь проект на fpc.
Мне вот интересно, эта бага проявляется при касте любого типа в более широкий? Или только 32 в 64?

И еще а тупо вот так

function MakeFullNumber( nSerial, nNumber: Integer ): Int64;
begin
  Result := nSerial * $FFFFFFFF + nNumber;
end;
разве не работает? Это же не Си, где тип результата определяется по операндам
20 июн 17, 14:48    [20577660]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2609
_Vasilisk_
function MakeFullNumber( nSerial, nNumber: Integer ): Int64;
begin
  Result := nSerial * $FFFFFFFF + nNumber;
end;

разве не работает? Это же не Си, где тип результата определяется по операндам

Не работает, я пробовал, еще и варнинг при этом (без явного каста) выдает что-то типа "Результат операции будет размером 64 бита".
20 июн 17, 16:13    [20578007]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2609
YuRock
Не работает, я пробовал, еще и варнинг при этом (без явного каста) выдает что-то типа "Результат операции будет размером 64 бита".

А результат тот же, что и при явном касте.
20 июн 17, 16:14    [20578014]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 2754
https://bugs.freepascal.org/view.php?id=32046
21 июн 17, 11:14    [20579827]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 2754
_Vasilisk_
Это же не Си, где тип результата определяется по операндам

У дельфей, кстати, если ожидается результат Int64, то один из операндов также должен быть Int64.
21 июн 17, 11:16    [20579835]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9990
Kazantsev Alexey
У дельфей, кстати, если ожидается результат Int64, то один из операндов также должен быть Int64.
Хм. Таки да
procedure TForm1.Button1Click(Sender: TObject);
var
  LVal1: Cardinal;
  LVal2: Cardinal;
  LRes1: Int64;
  LRes2: Int64;
begin
  LVal1 := $FFFFFFFF;
  LVal2 := $FFFFFFFF;
  LRes1 := LVal1 + LVal2;
  LRes2 := Int64(LVal1) + LVal2;
  MsgFmt('Res1: %d'#13#10'Res2: %d', [LRes1, LRes2]);
end;
Res1: 4294967294
Res2: 8589934590

При этом никаких хинтов и ворнингов
21 июн 17, 16:06    [20581064]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 2754
_Vasilisk_
При этом никаких хинтов и ворнингов

В доке об этом сказано:
http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Simple_Types_(Delphi)
In general, arithmetic operations on integers return a value of type Integer, which is equivalent to the 32-bit LongInt. Operations return a value of type Int64 only when performed on one or more Int64 operands.
21 июн 17, 16:31    [20581171]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
Bred eFeM
Member

Откуда:
Сообщений: 519
YuRock, пока остановился на этом
function MakeFullNumber( nSerial, nNumber: Integer ): Int64;
begin
  Result := $FFFFFFFF;
  Result := Result * nSerial;
  Result := Result + nNumber;
end;  
21 июн 17, 16:49    [20581241]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
Bred eFeM
Member

Откуда:
Сообщений: 519
YuRock, Под win64 та же история. ?

FPC 3.0.0 (lz 1.6.2) // Result -> ok

000000010002C429 894df8 mov DWORD PTR [rbp-0x8],ecx
000000010002C42C 8955f0 mov DWORD PTR [rbp-0x10],edx
unit1.pas:32 Result := Int64( nSerial ) * $FFFFFFFF + nNumber;
000000010002C42F 486345f8 movsxd rax,DWORD PTR [rbp-0x8] // ok
000000010002C433 48baffffffff00000000 movabs rdx,0xffffffff // ok
000000010002C43D 480fafc2 imul rax,rdx
000000010002C441 486355f0 movsxd rdx,DWORD PTR [rbp-0x10] // ok
000000010002C445 488d0410 lea rax,[rax+rdx*1]
000000010002C449 488945e8 mov QWORD PTR [rbp-0x18],rax
unit1.pas:33 end;


FPC 3.0.0 ( -O4 ) // Result -> ok

000000010002C427 89cb mov ebx,ecx
000000010002C429 89d6 mov esi,edx
unit1.pas:33 Result := Int64(nSerial) * $FFFFFFFF + nNumber;
000000010002C430 4863db movsxd rbx,ebx
000000010002C433 48b8ffffffff00000000 movabs rax,0xffffffff
000000010002C43D 480fafd8 imul rbx,rax
000000010002C441 4863f6 movsxd rsi,esi
000000010002C444 488d0433 lea rax,[rbx+rsi*1]



DX 10.2 // Result -> ok

00000000004263C8 894D20 mov [rbp+$20],ecx
00000000004263CB 895528 mov [rbp+$28],edx
Project1.dpr.12: Result := Int64( nSerial ) * $FFFFFFFF + nNumber;
00000000004263CE 48634520 movsxd rax,qword ptr [rbp+$20] // ? qword
00000000004263D2 C7C1FFFFFFFF mov ecx,$ffffffff // ? ecx
00000000004263D8 480FAFC1 imul rax,rcx
00000000004263DC 48634D28 movsxd rcx,qword ptr [rbp+$28] // ? qword
00000000004263E0 488D0408 lea rax,[rax+rcx]
00000000004263E4 48894508 mov [rbp+$08],rax
Project1.dpr.13: end;
21 июн 17, 16:55    [20581263]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2609
Bred eFeM
YuRock, пока остановился на этом

Нет, я уже переостановился на
( Int64( Serial ) and $FFFFFFFF )

Мне так больше нравится - хоть понимание, зачем это написано, есть.

Bred eFeM
FPC 3.0.0 ( -O4 ) // Result -> ok

Я запускал под win64 (изначальный вариант), в результате был мусор. С вариантом [выше] стало все правильно.
21 июн 17, 18:35    [20581587]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
Bred eFeM
Member

Откуда:
Сообщений: 519
YuRock, так у тебя and или * ?

а для x32 cpu signed($FFFFFFF) = -1 , если чё.
21 июн 17, 19:20    [20581691]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2609
Bred eFeM,

ну выше ж всё описано, вточности как в 1-м посту Василиск. Вначале and, а потом результат and *.
21 июн 17, 22:23    [20581974]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 2754
Kazantsev Alexey
https://bugs.freepascal.org/view.php?id=32046

Баг пофиксили.
6 янв 18, 19:40    [21084891]     Ответить | Цитировать Сообщить модератору
 Re: арифметика в FPC - cast Integer to Int64  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 2609
Ух ты, надо будет проверить, когда в релиз включат.
6 янв 18, 20:12    [21084941]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Delphi Ответить