Advertisement
Guest User

Untitled

a guest
Nov 2nd, 2019
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.21 KB | None | 0 0
  1. const c = @cImport({
  2.     @cInclude("/usr/include/gmp.h");
  3. });
  4. const std = @import("std");
  5. const Channel = std.event.Channel;
  6.  
  7. pub const io_mode = .evented;
  8.  
  9. pub fn main() !void {
  10.     try fact(30000000);
  11. }
  12.  
  13. fn fact(n: u64) !void {
  14.     var arena = std.heap.ArenaAllocator.init(std.heap.direct_allocator);
  15.     const allocator = &arena.allocator;
  16.  
  17.     const cores = try std.Thread.cpuCount();
  18.  
  19.     if (n < cores) {
  20.         var x: c.mpz_t = undefined;
  21.         c.mpz_init(&x);
  22.         mulrange(&x, 1, n);
  23.         c.mpz_clear(&x);
  24.         return;
  25.     }
  26.  
  27.     var buffer = try allocator.alloc(*c.mpz_t, cores);
  28.     var out = try allocator.create(Channel(*c.mpz_t));
  29.     out.init(buffer);
  30.  
  31.     var i: usize = 0;
  32.     while (i < cores) : (i += 1) {
  33.         (try allocator.create(@Frame(multrange))).* = async multrange(out, @divFloor(i * n, cores) + 1, @divFloor((i + 1) * n, cores));
  34.     }
  35.  
  36.     var in = out;
  37.     var procs = cores;
  38.  
  39.     while (procs > 1) {
  40.         buffer = try allocator.alloc(*c.mpz_t, procs);
  41.         out = try allocator.create(Channel(*c.mpz_t));
  42.         out.init(buffer);
  43.         var odd = procs % 2 == 1;
  44.         procs = @divFloor(procs, 2);
  45.         i = 0;
  46.         while (i < procs) : (i += 1) {
  47.             (try allocator.create(@Frame(mult))).* = async mult(in, out);
  48.         }
  49.         if (odd) {
  50.             out.put(in.get());
  51.             procs += 1;
  52.         }
  53.         in = out;
  54.     }
  55.  
  56.     var x = in.get();
  57.     c.mpz_clear(x);
  58. }
  59.  
  60. fn mult(in: *Channel(*c.mpz_t), out: *Channel(*c.mpz_t)) void {
  61.     const a = in.get();
  62.     const b = in.get();
  63.  
  64.     c.mpz_mul(a, a, b);
  65.     out.put(a);
  66.     c.mpz_clear(b);
  67. }
  68.  
  69. fn multrange(out: *Channel(*c.mpz_t), a: u64, b: u64) void {
  70.     var x: c.mpz_t = undefined;
  71.     c.mpz_init(&x);
  72.     mulrange(&x, a, b);
  73.     out.put(&x);
  74. }
  75.  
  76. fn mulrange(out: *c.mpz_t, a: u64, b: u64) void {
  77.     if (a == b) {
  78.         c.mpz_init_set_ui(out, a);
  79.         return;
  80.     }
  81.  
  82.     var l: c.mpz_t = undefined;
  83.     c.mpz_init(&l);
  84.     var r: c.mpz_t = undefined;
  85.     c.mpz_init(&r);
  86.  
  87.     const m = @divFloor((a + b), 2);
  88.     mulrange(&l, a, m);
  89.     mulrange(&r, m + 1, b);
  90.  
  91.     c.mpz_mul(out, &l, &r);
  92.  
  93.     c.mpz_clear(&l);
  94.     c.mpz_clear(&r);
  95. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement