@@ -341,8 +341,54 @@ let rec of_float (x : float) : t =
341
341
external log2 : float = " LN2" [@@ bs.val] [@@ bs.scope "Math" ]
342
342
external log : float -> float = " log" [@@ bs.val] [@@ bs.scope "Math" ]
343
343
external ceil : float -> float = " ceil" [@@ bs.val] [@@ bs.scope "Math" ]
344
+ external floor : float -> float = " floor" [@@ bs.val] [@@ bs.scope "Math" ]
344
345
(* external maxFloat : float -> float -> float = "Math.max" [@@bs.val] *)
345
346
347
+ (* either top 11 bits are all 0 or all 1
348
+ when it is all 1, we need exclude -2^53
349
+ *)
350
+ let isSafeInteger (Int64{hi;lo} ) =
351
+ let top11Bits = hi >> 21 in
352
+ top11Bits = 0n ||
353
+ (top11Bits = - 1n &&
354
+ Pervasives. not (lo = 0n && hi = (0xff_e0_00_00n |~ 0n )))
355
+
356
+ external string_of_float : float -> string = " String" [@@ bs.val]
357
+ let rec to_string ( self : int64 ) =
358
+ let (Int64 {hi= self_hi;_} as self) = unsafe_of_int64 self in
359
+ if isSafeInteger self then
360
+ string_of_float (to_float self)
361
+ else
362
+
363
+ if self_hi < 0n then
364
+ if eq self min_int then " -9223372036854775808"
365
+ else " -" ^ to_string (unsafe_to_int64 (neg self))
366
+ else (* large positive number *)
367
+ let (Int64 {lo ; hi} as approx_div1) = (of_float (floor (to_float self /. 10. ) )) in
368
+ let (Int64 { lo = rem_lo ;hi = rem_hi} ) = (* rem should be a pretty small number *)
369
+ self
370
+ |. sub_aux ~lo: (lo << 3 ) ~hi: ((lo>>> 29 ) |~ (hi << 3 ))
371
+ |. sub_aux ~lo: (lo << 1 ) ~hi: ((lo >>> 31 ) |~ (hi << 1 ))
372
+ in
373
+ if rem_lo = 0n && rem_hi = 0n then to_string (unsafe_to_int64 approx_div1) ^ " 0"
374
+ else
375
+ if rem_hi < 0n then
376
+ (* let (Int64 {lo = rem_lo}) = neg rem in *)
377
+ let rem_lo = to_unsigned ((lognot rem_lo +~ 1n ) & 0xffff_ffffn ) |. Caml_nativeint_extern. to_float in
378
+ let delta = (ceil (rem_lo /. 10. )) in
379
+ let remainder = 10. *. delta -. rem_lo in
380
+ to_string (unsafe_to_int64 (sub_lo approx_div1
381
+ (Caml_nativeint_extern. of_float delta))) ^
382
+ Caml_nativeint_extern. to_string (Caml_nativeint_extern. of_float remainder)
383
+ else
384
+ let rem_lo = Caml_nativeint_extern. to_float rem_lo in
385
+ let delta = (floor (rem_lo /. 10. )) in
386
+ let remainder = rem_lo -. 10. *. delta in
387
+ to_string (unsafe_to_int64 (add_lo approx_div1 ((Caml_nativeint_extern. of_float delta)))) ^
388
+ Caml_nativeint_extern. to_string (Caml_nativeint_extern. of_float remainder)
389
+
390
+
391
+
346
392
let rec div self other =
347
393
match self, other with
348
394
| _ , Int64 {lo = 0n ; hi = 0n } ->
0 commit comments