123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200(*
* BatInt32 - Extended 32-bit integers
* Copyright (C) 2007 Bluestorm <bluestorm dot dylc on-the-server gmail dot com>
* 2008 David Teller
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version,
* with the special exception on linking described in file LICENSE.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)openBatNumberlet(|>)xf=fxletto_byten=Int32.logand0xffln|>Int32.to_int|>Char.chrletof_byteb=Char.codeb|>Int32.of_int(*$Q to_byte; of_byte
Q.char (fun c -> to_byte (of_byte c) = c)
*)(*$T to_byte
to_byte 256l = to_byte 0l
*)(* really need to just blit an int32 word into a string and vice versa *)letpackstrpositem=ifBytes.lengthstr<pos+4theninvalid_arg "Int32.pack: pos too close to end of string";ifpos<0theninvalid_arg"Int32.pack: pos negative";Bytes.setstrpos(to_byteitem);letitem=Int32.shift_rightitem8inBytes.setstr(pos+1)(to_byteitem);letitem=Int32.shift_rightitem8inBytes.setstr(pos+2)(to_byteitem);letitem=Int32.shift_rightitem8inBytes.setstr(pos+3)(to_byteitem)(*optimize out last logand? *)(*$T pack
let str = Bytes.of_string " " in pack str 0 0l; (Bytes.to_string str = "\000\000\000\000")
let str = Bytes.of_string " " in pack str 0 0l; (Bytes.to_string str = "\000\000\000\000 ")
let str = Bytes.of_string " " in pack str 1 0l; (Bytes.to_string str = " \000\000\000\000")
let str = Bytes.of_string " " in try pack str 0 0l; false with Invalid_argument _ -> true
let str = Bytes.of_string " " in try pack str 1 0l; false with Invalid_argument _ -> true
*)letpack_bigstrpositem=ifBytes.lengthstr<pos+4theninvalid_arg "Int32.pack_big: pos too close to end of string";ifpos<0theninvalid_arg"Int32.pack_big: pos negative";Bytes.setstr(pos+3)(to_byteitem);letitem=Int32.shift_rightitem8inBytes.setstr(pos+2)(to_byteitem);letitem=Int32.shift_rightitem8inBytes.setstr(pos+1)(to_byteitem);letitem=Int32.shift_rightitem8inBytes.setstrpos(to_byteitem)(*optimize out last logand? *)(*$T pack_big
let str = Bytes.of_string " " in pack_big str 0 0l; (Bytes.to_string str = "\000\000\000\000")
let str = Bytes.of_string " " in pack_big str 0 0l; (Bytes.to_string str = "\000\000\000\000 ")
let str = Bytes.of_string " " in pack_big str 1 0l; (Bytes.to_string str = " \000\000\000\000")
let str = Bytes.of_string " " in try pack_big str 0 0l; false with Invalid_argument _ -> true
let str = Bytes.of_string " " in try pack_big str 1 0l; false with Invalid_argument _ -> true
*)letunpackstrpos=ifBytes.lengthstr<pos+4theninvalid_arg"Int32.unpack: pos + 4 not within string";ifpos<0theninvalid_arg"Int32.unpack: pos negative";letshiftn=Int32.shift_leftn8andaddbn=Int32.add(of_byteb)ninof_byte (Bytes.unsafe_getstr(pos+3))|>shift|> add(Bytes.unsafe_getstr(pos+2))|>shift|> add(Bytes.unsafe_getstr(pos+1))|>shift|> add(Bytes.unsafe_getstrpos)(* TODO: improveperformance of bit twiddling? will these curried functions get inlined? *)(*$T unpack
unpack (Bytes.of_string "\000\000\000\000") 0 = 0l
unpack (Bytes.of_string "\000\000\000\000 ") 0 = 0l
unpack (Bytes.of_string " \000\000\000\000") 1 = 0l
unpack (Bytes.of_string "\255\000\000\000") 0 = 255l
*)(*$Q pack; unpack
Q.int (let str = Bytes.of_string " " in fun x -> let x = Int32.of_int x in pack str 0 x; unpack str 0 = x)
*)letunpack_bigstrpos=ifBytes.lengthstr<pos+4theninvalid_arg "Int32.unpack_big: pos + 4 not within string";ifpos<0theninvalid_arg"Int32.unpack_big: pos negative";letshiftn=Int32.shift_leftn8andaddbn=Int32.add(of_byteb)ninof_byte (Bytes.unsafe_getstrpos)|>shift|>add(Bytes.unsafe_getstr(pos+1))|>shift|> add(Bytes.unsafe_getstr(pos+2))|>shift|> add(Bytes.unsafe_getstr(pos+3))(*$T unpack_big
unpack_big (Bytes.of_string "\000\000\000\000") 0 = 0l
unpack_big (Bytes.of_string "\000\000\000\000 ") 0 = 0l
unpack_big (Bytes.of_string " \000\000\000\000 ") 1 = 0l
unpack_big (Bytes.of_string "\000\000\000\255") 0 = 255l
*)(*$Q pack_big; unpack_big
Q.int (let str = Bytes.of_string " " in fun x -> let x = Int32.of_int x in pack_big str 0 x; unpack_big str 0 = x)
*)moduleBaseInt32=structincludeInt32letmodulo=remletpow=generic_pow ~zero~one~div_two:(funn->shift_rightn1)~mod_two:(logandone)~mul:mul(*$T pow
pow one one = one
pow one zero = one
pow zero one = zero
pow zero zero = one
pow one one = one
pow (neg one) one = neg one
try ignore (pow one (of_int ~-1)) ; false \
with Invalid_argument _ -> true | _ -> false
*)endincludeBatNumber.MakeNumeric(BaseInt32)letmin_int =Int32.min_intletmax_int=Int32.max_intletminus_one=Int32.minus_oneletlognot=Int32.lognotexternalneg:int32->int32="%int32_neg"externaladd:int32->int32->int32="%int32_add"externalsub:int32->int32->int32="%int32_sub"externalmul:int32->int32->int32="%int32_mul"externaldiv:int32->int32->int32="%int32_div"externalrem:int32->int32->int32="%int32_mod"externallogand:int32->int32->int32="%int32_and"externallogor:int32->int32->int32="%int32_or"externallogxor:int32 ->int32->int32="%int32_xor"externalshift_left:int32->int->int32="%int32_lsl"externalshift_right:int32->int->int32="%int32_asr"externalshift_right_logical :int32->int->int32="%int32_lsr"externalof_int:int->int32="%int32_of_int"externalto_int:int32 ->int="%int32_to_int"externalof_float:float ->int32="caml_int32_of_float"##V>=4.3##"caml_int32_of_float_unboxed"[@@unboxed][@@noalloc]externalto_float :int32->float="caml_int32_to_float"##V>=4.3##"caml_int32_to_float_unboxed"[@@unboxed][@@noalloc]external of_string:string->int32="caml_int32_of_string"##V>=4.5##letof_string_opt=Int32.of_string_opt##V<4.5##letof_string_optn=trySome(Int32.of_stringn)with_->Noneexternalof_int64:int64->int32 ="%int64_to_int32"externalto_int64:int32->int64="%int64_of_int32"externalof_nativeint:nativeint->int32="%nativeint_to_int32"external to_nativeint:int32->nativeint="%nativeint_of_int32"externalbits_of_float:float->int32="caml_int32_bits_of_float"##V>=4.3##"caml_int32_bits_of_float_unboxed"[@@unboxed][@@noalloc]externalfloat_of_bits:int32->float="caml_int32_float_of_bits"##V>=4.3##"caml_int32_float_of_bits_unboxed"[@@unboxed][@@noalloc]externalformat:string->int32->string="caml_int32_format"##V>=4.08##letunsigned_div=Int32.unsigned_div##V>=4.08##letunsigned_rem=Int32.unsigned_rem##V>=4.08##letunsigned_to_int =Int32.unsigned_to_int##V>=4.08##letunsigned_compare =Int32.unsigned_comparetypebounded=tletmin_num,max_num =min_int,max_intletprintoutt=BatInnerIO.nwriteout(to_stringt)letprint_hexoutt=BatPrintf.fprintfout"%lx"tletmin(x:t)(y:t):t=ifx<=ythenxelseyletmax(x:t)(y:t):t=ifx>=ythenxelsey##V>=5.1##letseeded_hash=Int32.seeded_hash##V>=5.1##lethash=Int32.hash