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
  
102
  
103
  
104
  
105
  
106
  
107
  
108
  
109
  
110
  
111
  
112
  
113
  
114
  
115
  
#pike __REAL_VERSION__ 
#pragma strict_types 
 
//!   Generic lightweight range type.  Supports any values for lower 
//!   and upper boundaries that implement the @expr{`<@} lfun. 
//! @note 
//!   Can only contain a single contiguous range. 
 
//!  The lower inclusive boundary. 
mixed from; 
 
//!  The upper exclusive boundary. 
mixed till; 
 
array(mixed) _encode() { 
  return ({from, till}); 
} 
 
void _decode(array(mixed) x) { 
  from = x[0]; 
  till = x[1]; 
} 
 
//! @param from 
//!   Lower inclusive boundary for the range.  Specify no lower-boundary 
//!   by filling in @expr{-Math.inf@}. 
//! @param till 
//!   Upper exclusive boundary for the range.  Specify no upper-boundary 
//!   by filling in @expr{Math.inf@}. 
//! @seealso 
//!   [Math.inf] 
protected variant void create(mixed from, mixed till) { 
  this::from = from; 
  this::till = till; 
} 
protected variant void create(object/*this_program*/ copy) { 
  from = copy->from; 
  till = copy->till; 
} 
protected variant void create() { 
} 
 
//! Difference 
protected mixed `-(mixed that) { 
  this_program n = this_program(max(from, ([object]that)->from), 
                                min(till, ([object]that)->till)); 
  if (n->from >= n->till) 
    return this; 
  if (till == n->till) { 
    n->till = n->from; 
    n->from = from; 
    return n; 
  } 
  if (from == n->from) { 
    n->from = n->till; 
    n->till = till; 
    return n; 
  } 
  error("Result of range difference would not be contiguous\n"); 
} 
 
//! Union 
protected mixed `+(mixed that) { 
  if (from != ([object]that)->till && ([object]that)->from != till 
      && !(this & ([object]that))) 
    error("Result of range union would not be contiguous\n"); 
  return this_program(min(from, ([object]that)->from), 
                      max(till, ([object]that)->till)); 
} 
 
//! Intersection 
protected mixed `*(mixed that) { 
  return this_program(max(from, ([object]that)->from), 
                      min(till, ([object]that)->till)); 
} 
 
//! Overlap: have points in common. 
protected int(0..1) `&(mixed that) { 
  return till > ([object]that)->from && ([object]that)->till > from; 
} 
 
protected int(0..1) `<(mixed that) { 
  return from < ([object]that)->from 
    || from == ([object]that)->from && till < ([object]that)->till; 
} 
 
protected int(0..1) `==(mixed that) { 
  return objectp(that) 
   && from == ([object]that)->from && till == ([object]that)->till; 
} 
 
//! @returns 
//!   Calculates the value of the interval: @expr{till - from@}. 
mixed interval() { 
  return till - from; 
} 
 
//! Casting a range to string delivers an SQL-compliant value. 
protected mixed cast(string to) { 
  if (to == "string") 
    return from >= till ? "empty" : sprintf("%c%s,%s)", 
      from == -Math.inf ? '(' : '[', from == -Math.inf ? "" : (string)from, 
      till == Math.inf ? "" : (string)till); 
  return UNDEFINED; 
} 
 
protected string _sprintf(int fmt, mapping(string:mixed) params) { 
  switch (fmt) { 
    case 'O': return sprintf("this_program( %s )", (string)this); 
    case 's': return (string)this; 
  } 
  return sprintf(sprintf("%%*%c", fmt), params, 0); 
}