From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=AWL autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by yquem.inria.fr (Postfix) with ESMTP id 62DE9BBCA for ; Thu, 3 Apr 2008 19:15:52 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: ApoEAHOt9EfAXQIm/2dsb2JhbACsGg X-IronPort-AV: E=Sophos;i="4.25,599,1199660400"; d="scan'208";a="24564671" Received: from discorde.inria.fr ([192.93.2.38]) by mail4-smtp-sop.national.inria.fr with ESMTP; 03 Apr 2008 19:15:52 +0200 Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by discorde.inria.fr (8.13.6/8.13.6) with ESMTP id m33HFo0Q028650 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=OK) for ; Thu, 3 Apr 2008 19:15:51 +0200 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AjwCAMit9EdQRFuwiGdsb2JhbACRVwEBAQ8mmgo X-IronPort-AV: E=Sophos;i="4.25,599,1199660400"; d="scan'208";a="11036450" Received: from furbychan.cocan.org ([80.68.91.176]) by mail3-smtp-sop.national.inria.fr with ESMTP; 03 Apr 2008 19:15:51 +0200 Received: from rich by furbychan.cocan.org with local (Exim 4.63) (envelope-from ) id 1JhT2U-00058k-A3; Thu, 03 Apr 2008 18:15:50 +0100 Date: Thu, 3 Apr 2008 18:15:50 +0100 To: =?utf-8?Q?Micha=C5=82?= Maciejewski Cc: caml-list@inria.fr Subject: Re: [Caml-list] Operators for Int64 and Int32 Message-ID: <20080403171549.GA18505@annexia.org> References: <906164100804030708p3e2788a0p29b69f4d46600622@mail.gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <906164100804030708p3e2788a0p29b69f4d46600622@mail.gmail.com> User-Agent: Mutt/1.5.13 (2006-08-11) From: Richard Jones X-Miltered: at discorde with ID 47F510C6.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; 0200,:01 ocaml:01 ocaml:01 stdlib:01 functors:01 struct:01 logor:01 pred:01 pred:01 functor:01 sig:01 val:01 val:01 sig:01 bool:01 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 C-structure-parsing 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^bits-1. *) 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^bits-1. *) 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 bit-operating 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^bits-1. *) 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