[go: up one dir, main page]

File: adviUnits.ml

package info (click to toggle)
advi 1.10.2-3
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 15,008 kB
  • sloc: ml: 12,279; sh: 1,032; ansic: 1,016; makefile: 705; perl: 55
file content (101 lines) | stat: -rw-r--r-- 3,011 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
(***********************************************************************)
(*                                                                     *)
(*                             Active-DVI                              *)
(*                                                                     *)
(*                   Projet Cristal, INRIA Rocquencourt                *)
(*                                                                     *)
(*  Copyright 2002 Institut National de Recherche en Informatique et   *)
(*  en Automatique.  All rights reserved.  This file is distributed    *)
(*  under the terms of the GNU Lesser General Public License.          *)
(*                                                                     *)
(*  Jun Furuse, Didier Rmy and Pierre Weis.                           *)
(*  Contributions by Roberto Di Cosmo, Didier Le Botlan,               *)
(*  Xavier Leroy, and Alan Schmitt.                                    *)
(*                                                                     *)
(*  Based on Mldvi by Alexandre Miquel.                                *)
(***********************************************************************)

(* $Id: adviUnits.ml,v 1.1 2009/01/23 16:28:48 maranget Exp $ *)

type units =
  | PT
  | PC
  | IN
  | BP
  | CM
  | MM
  | DD
  | CC
  | SP ;;

(*** Rational arithmetic ***)

let rec unsafe_gcd big small =
  if small = 0 then big else
  unsafe_gcd small (big mod small) ;;

let gcd a b =
  if a > b then unsafe_gcd a b else
  if a < b then unsafe_gcd b a else a ;;

let simplify (num, den) =
  let d = gcd num den in
  (num/d, den/d) ;;

let rec mag n =
  if n = 0 then 0 else
  1 + mag (n/2) ;;

let mul (n1, d1) (n2, d2) =
  simplify (n1 * n2, d1 * d2) ;;

let div r (n, d) =
  mul r (d, n) ;;

let conv_list = ref [PT, (1, 1)] ;;

let set k1 u1 (* = *) k2 u2 =
  assert (not (List.mem_assoc u1 !conv_list)) ;
  let r2 = List.assoc u2 !conv_list in
  let r1 = mul r2 (k2, k1) in
  conv_list := (u1, r1) :: !conv_list ;;

(* Convertion ratios (source: D. Knuth, The TeXbook 1986, Addisson-Wesley) *)

set 1 PC (* = *) 12 PT ;;
set 100 IN (* = *) 7227 PT ;;
set 72 BP (* = *) 1 IN ;;
set 254 CM (* = *) 100 IN ;;
set 10 MM (* = *) 1 CM ;;
set 1157 DD (* = *) 1238 PT ;;
set 1 CC (* = *) 12 DD ;;
set 65536 SP (* = *) 1 PT ;;

let int_of_units = function
  | PT -> 0 | PC -> 1 | IN -> 2
  | BP -> 3 | CM -> 4 | MM -> 5
  | DD -> 6 | CC -> 7 | SP -> 8 ;;

let units_of_int = function
  | 0 -> PT | 1 -> PC | 2 -> IN
  | 3 -> BP | 4 -> CM | 5 -> MM
  | 6 -> DD | 7 -> CC | 8 -> SP
  | _ -> assert false ;;

let matrix = Array.create_matrix 9 9 (0, 0) ;;

for i = 0 to 8 do
  for j = 0 to 8 do
    let ri = List.assoc (units_of_int i) !conv_list
    and rj = List.assoc (units_of_int j) !conv_list in
    matrix.(i).(j) <- div rj ri
  done
done ;;

let ratio u1 u2 =
  matrix.(int_of_units u1).(int_of_units u2) ;;

let from_to u1 u2 =
  let (n1, n2) = ratio u1 u2 in
  let f = float n2 /. float n1 in
  function x -> f *. x ;;