Просмотр исходного кода

upd factorial - u128, return string

221V 1 неделя назад
Родитель
Сommit
c88b72b6ec
2 измененных файлов с 47 добавлено и 12 удалено
  1. 8 8
      README.md
  2. 39 4
      niftest.zig

+ 8 - 8
README.md

@@ -18,18 +18,18 @@ Eshell V13.2  (abort with ^G)
 2> niftest:hello().
 "Hello world!"
 3> niftest:factorial(5).
-120
+"120"
 4> niftest:factorial(20).
-2432902008176640000
-5> niftest:factorial(21).
-** exception error: bad argument
-     in function  niftest:factorial/1
-        called as niftest:factorial(21)
-6> niftest:factorial(-5).
+"2432902008176640000"
+5> niftest:factorial(34).
+"295232799039604140847618609643520000000"
+6> niftest:factorial(35).
+{error,"input too large, max is 34"}
+7> niftest:factorial(-5).
 ** exception error: bad argument
      in function  niftest:factorial/1
         called as niftest:factorial(-5)
-7>q().
+8> q().
 
 
 

+ 39 - 4
niftest.zig

@@ -13,24 +13,59 @@ pub export fn hello(env: ?*erl.ErlNifEnv, argc: c_int, argv: [*c]const erl.ERL_N
 }
 
 
+fn u128_to_buf(value: u128, buffer: *align(1) [40]u8) usize{
+  if(value == 0){
+    buffer[0] = '0';
+    return 1;
+  }
+  
+  var i: usize = 0;
+  var n = value;
+  while(n > 0){
+    buffer[i] = @as(u8, @intCast('0' + (n % 10)) );
+    n /= 10;
+    i += 1;
+  }
+  
+  var j: usize = 0;
+  while(j < i / 2) : (j += 1){
+    const temp = buffer[j];
+    buffer[j] = buffer[i - 1 - j];
+    buffer[i - 1 - j] = temp;
+  }
+  
+  return i;
+}
+
+
 pub export fn factorial(env: ?*erl.ErlNifEnv, argc: c_int, argv: [*c]const erl.ERL_NIF_TERM) erl.ERL_NIF_TERM{
   if(argc != 1){
     return erl.enif_make_badarg(env);
   }
   
   var n: c_long = undefined;
-  if(erl.enif_get_long(env, argv[0], &n) == 0 or n < 0 or n > 20){
+  if(erl.enif_get_long(env, argv[0], &n) == 0 or n < 0){
     return erl.enif_make_badarg(env);
   }
   
-  var result: c_ulonglong = 1;
-  var i: c_ulonglong = @as(c_ulonglong, @intCast(n) );
+  if(n > 34){ // max n for max factorial for u128
+    return erl.enif_make_tuple2(env,
+      erl.enif_make_atom(env, "error"),
+      erl.enif_make_string(env, "input too large, max is 34", 1)
+    );
+  }
+  
+  var result: u128 = 1;
+  var i = @as(u128, @intCast(n) );
   //var i = n;
   while(i > 1) : (i -= 1){
     result *= i;
   }
   
-  return erl.enif_make_uint64(env, result);
+  var buf: [40]u8 = undefined;
+  const len = u128_to_buf(result, &buf);
+  
+  return erl.enif_make_string_len(env, buf[0..len].ptr, len, 1); // , ERL_NIF_LATIN1);
 }