[Camllist] Operators for Int64 and Int32
[
Home
]
[ Index:
by date

by threads
]
[ Message by date: previous  next ] [ Message in thread: previous  next ] [ Thread: previous  next ]
[ Message by date: previous  next ] [ Message in thread: previous  next ] [ Thread: previous  next ]
Date:  20080403 (17:15) 
From:  Richard Jones <rich@a...> 
Subject:  Re: [Camllist] Operators for Int64 and Int32 
On Thu, Apr 03, 2008 at 04:08:00PM +0200, MichaÅ‚ Maciejewski wrote: > I'm quite new to OCaml but recently I had to write a wave file parsing > application. I've decided to try OCaml instead of C++. The first > problem I've encountered was of course too short native Integer type > for representing some values in wave file header. So I was forced to > use int64 type instead. Yes, this is indeed an area where you have to be careful. I'm writing similar Cstructureparsing code and it is painful having to convert between int/int32/int64 although of course there are good reasons for it. > The best solutions to those problem would be in my opinion to add > something like this to standard library (to new module): > > let ( +^^ ) a b = Int64.add a b [etc.] Yes, my code defines these operators too, although I picked slightly different names for them, so perhaps it would be worth having these in the stdlib if only because at least everyone would have the same name for them :) Another thing you can do is to use functors to simplify writing code that must work on int, int32 and int64 types. eg take a basic function like this: (* Check a value is in range 0 .. 2^bits1. *) let range_unsigned v bits = let mask = lnot (mask bits) in (v land mask) = zero The above function only works for ints. But the same source code could work for int32 as well, if you defined a few functions that you need. Note that the source of 'range_unsigned' is exactly the same below as above: module I32 = struct let (<<) = Int32.shift_left let (>>) = Int32.shift_right_logical let (land) = Int32.logand let (lor) = Int32.logor let lnot = Int32.lognot let pred = Int32.pred let max_int = Int32.max_int let to_int = Int32.to_int let zero = Int32.zero let one = Int32.one let minus_one = Int32.minus_one let ff = 0xff_l (* Create a mask so many bits wide. *) let mask bits = if bits < 31 then pred (one << bits) else if bits = 31 then max_int else if bits = 32 then minus_one else invalid_arg "Bitmatch.I32.mask" (* Check a value is in range 0 .. 2^bits1. *) let range_unsigned v bits = let mask = lnot (mask bits) in (v land mask) = zero end (There's a few extra base functions in there because this example is pulled from some real code which does the same thing over a collection of bitoperating functions). This can be converted into a functor relatively easily: module type IntegerType = sig type t val (<<) : t > int > t val (>>) : t > int > t val (land) : t > t > t val (lor) : t > t > t val lnot : t > t val pred : t > t val max_int : t val to_int : t > int val zero : t val one : t val minus_one : t val ff : t val mask : int > t end module type S = sig type t val range_unsigned : t > int > bool end module Make (I : IntegerType) : S with type t = I.t = struct include I (* Check a value is in range 0 .. 2^bits1. *) let range_unsigned v bits = let mask = lnot (mask bits) in (v land mask) = zero end And now you can use the functor to build int/int32/int64 versions of the "range_unsigned" function automatically. Of course this example is a lot more worthwhile if you have a whole lot of these functions, not just one :) (* Make the module for int *) module I = Make (struct type t = int include Pervasives let (<<) = (lsl) let (>>) = (lsr) external to_int : int > int = "%identity" let zero = 0 let one = 1 let minus_one = 1 let ff = 0xff (* Create a mask so many bits wide. *) let mask bits = if bits < 30 then pred (one << bits) else if bits = 30 then max_int else if bits = 31 then minus_one else invalid_arg "Bitmatch.I.mask" end) (* Make the module for int32 *) module I32 = Make (struct include Int32 let (<<) = Int32.shift_left let (>>) = Int32.shift_right_logical let (land) = Int32.logand let (lor) = Int32.logor let lnot = Int32.lognot let ff = 0xff_l (* Create a mask so many bits wide. *) let mask bits = if bits < 31 then pred (one << bits) else if bits = 31 then max_int else if bits = 32 then minus_one else invalid_arg "Bitmatch.I32.mask" end) To check the functions have been defined: let () = ignore (I.range_unsigned 1 10); (* the int version *) ignore (I32.range_unsigned 1_l 10); (* the int32 version *) Rich.  Richard Jones Red Hat