@@ -341,8 +341,54 @@ let rec of_float (x : float) : t =
341341external log2 : float = " LN2" [@@ bs.val] [@@ bs.scope "Math" ]
342342external log : float -> float = " log" [@@ bs.val] [@@ bs.scope "Math" ]
343343external ceil : float -> float = " ceil" [@@ bs.val] [@@ bs.scope "Math" ]
344+ external floor : float -> float = " floor" [@@ bs.val] [@@ bs.scope "Math" ]
344345(* external maxFloat : float -> float -> float = "Math.max" [@@bs.val] *)
345346
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+
346392let rec div self other =
347393 match self, other with
348394 | _ , Int64 {lo = 0n ; hi = 0n } ->
0 commit comments