Dapatkan modulo dari dua array integer 4x64bit

Saya menggunakan OpenCL untuk pemrograman GPGPU, tapi sayangnya tidak ada dukungan integer 256 bit asli. Saya memutuskan untuk membagi bilangan bulat 256 bit menjadi empat bilangan bulat 64bit. Solusi yang cukup bagus untuk operasi dasar, tetapi bagaimana saya bisa mendapatkan modulonya?

Saya perlu melakukan hal ini:

(uint256) % (uint256)

Tapi dengan OpenCL, saya hanya bisa memiliki ini:

[ (uint64), (uint64), (uint64), (uint64) ] % [ (uint64), (uint64), (uint64), (uint64) ]

Jadi bagaimana saya bisa mencapainya? Algoritma apa yang harus saya gunakan, dan yang paling penting - algoritma apa yang paling mudah diterapkan?

P.S. Saya memerlukannya untuk kriptografi kunci publik.

EDIT: Saya tidak menerapkan penambahan maupun pengurangan.


person Alex S.    schedule 06.06.2020    source sumber
comment
Terima kasih! Apakah Anda punya bacaan yang direkomendasikan?   -  person Alex S.    schedule 06.06.2020
comment
Bisakah kamu melakukan apa pun yang kamu inginkan dengan pensil? Temukan bebek karet... bicara pelan-pelan... Sudahkah Anda mempertimbangkan beberapa perpustakaan presisi yang diperluas? Jadi... sepertinya Anda belum mencoba apa pun. Harap tinjau contoh minimal yang dapat direproduksi.   -  person 2785528    schedule 06.06.2020
comment
Saya mencoba mencarinya di Google, tetapi saya belum menemukan apa pun. OpenCL tidak seperti C/C++, dan tidak ada perpustakaan seperti gmp dan lainnya.   -  person Alex S.    schedule 06.06.2020
comment
Saya tidak menerapkan penambahan atau pengurangan. ---› Apakah Anda memerlukan bantuan untuk penambahan?   -  person chux - Reinstate Monica    schedule 07.06.2020
comment
Dengan penambahan pengurangan. Saya akan sangat berterima kasih.   -  person Alex S.    schedule 07.06.2020
comment
Cobalah pustaka gmp GNU Multiprecision, yang sudah mengimplementasikan semua yang Anda perlukan, dan merupakan dasar dari banyak kode pustaka kriptografi .   -  person Luis Colorado    schedule 08.06.2020
comment
Saya menggunakan OpenCL C, dan tidak ada yang namanya perpustakaan. Tentu saja saya akan menggunakannya jika saya bekerja dengan C/C++.   -  person Alex S.    schedule 08.06.2020


Jawaban (1)


Berikut adalah algoritma yang mudah (dan cukup efisien) yang menghitung a % b hanya dengan menggunakan pengurangan, perkalian dengan 2, pembagian dengan 2 dan perbandingan (semuanya mudah diterapkan untuk uint256 Anda).

uint256 modulo(uint256 a, uint256 b) {
  int i = 0;
  while (b <= a) {
    b = b * 2; // watch out for overflow!
    i++;
  }
  while (i--) {
    b = b / 2;
    if (b <= a) {
      a = a - b;
    }
  }
  return a;
}

Berikut ini contohnya:

start: a = 40, b = 7
i = 1, a = 40, b = 14
i = 2, a = 40, b = 28
i = 3, a = 40, b = 56

i = 3, b = 28, a = 40 - 28 = 12
i = 2, b = 14, a = 12 (b > a so nothing happens)
i = 1, b = 7, a = 12 - 7 = 5
i = 0, so we stop and return a = 5

EDIT: Mengapa ini berhasil? Cara naif menghitung residu modulo jika sebagai berikut:

int modulo(int a, int b) {
  while (a >= b) {
    a -= b;
  }
  return a;
}

Solusi yang diusulkan menggunakan ide yang sama, namun dengan cara yang lebih efisien. Kita tahu bahwa kita akan mendapatkan pengurangan b dari a tepat k kali. Oleh karena itu kita tidak mengetahui nilai k. k dapat direpresentasikan dalam biner sebagai 2^0 * k_0 + 2^1 * k_1 + 2^2 * k_2 + .... Algoritme beralih dari nilai terbesar 2^i dan mencoba mengurangi 2^i * b. Berkat itu kami mencapai kompleksitas waktu logaritmik, bukan linier.

Penafian: Saya tidak akan menggunakan implementasi ini sebagai implementasi kriptografi nyata karena rentan terhadap serangan saluran samping (waktu eksekusi berbeda tergantung pada input).

person Igor    schedule 06.06.2020
comment
Baiklah, saya bertanya bagaimana cara mengimplementasikan modulo untuk dua array integer 4x64bit, bukan untuk dua uint256. Intinya adalah saya hanya bisa bekerja dengan bilangan bulat 64 bit. - person Alex S.; 06.06.2020
comment
@AlexanderSadovskyi Anda menyebutkan bahwa solusi yang cukup bagus untuk operasi dasar, jadi saya berasumsi Anda sudah menerapkan operasi dasar seperti pengurangan. Algoritme di atas berfungsi untuk implementasi bilangan bulat apa pun, selama Anda dapat melakukan 4 operasi yang disebutkan di awal. Ganti saja mis. b = b * 2 dengan implementasi Anda mengalikan uint256 dengan 2 (yang mudah), dll. - person Igor; 06.06.2020
comment
Maksud saya operasi bitwise dasar. Saya tidak menerapkan apa pun karena yang saya perlukan hanyalah mendapatkan modulo. - person Alex S.; 07.06.2020
comment
Bisakah Anda menambahkan cara untuk memikirkan mengapa ini berhasil? - person גלעד ברקן; 07.06.2020
comment
@גלעדברקן Penjelasan tambahan - person Igor; 08.06.2020