File: pg_rational_test.sql

package info (click to toggle)
pg-rational 0.0.2-8
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 156 kB
  • sloc: ansic: 471; sql: 408; makefile: 12; sh: 1
file content (271 lines) | stat: -rw-r--r-- 6,388 bytes parent folder | download | duplicates (4)
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
create extension pg_rational;
set client_min_messages to error;

-- I/O

-- can parse a simple fraction
select '1/3'::rational;
-- can parse negatives
select '-1/3'::rational;
select '1/-3'::rational;
-- SEND works
select rational_send('1/3');

-- casting

-- tuple helper
select (1,2)::ratt = '1/2'::rational;
-- int
select 42 = '42/1'::rational;

-- from float
select 0.263157894737::float::rational;
select 3.141592625359::float::rational;
select 0.606557377049::float::rational;
select -0.5::float::rational;
select 1.000001::float::rational;
select 1.0000001::float::rational;
select 1.00000001::float::rational;
select 1.000000001::float::rational;
select 1.0000000001::float::rational;
select 2147483647::float::rational;
select 2147483647.1::float::rational;
select 'NAN'::float::rational;

-- to float
select '1/2'::rational::float;
set extra_float_digits = 0; -- default changed in PG12
select '1/3'::rational::float;
reset extra_float_digits;
select '-1/2'::rational::float;

-- too big
select '2147483648/2147483647'::rational;
-- no spaces
select '1 /3'::rational;
-- no zero denominator
select '1/0'::rational;
-- quoted number treated as int
select '1'::rational;
select '-1'::rational;
-- no garbage
select ''::rational;
select '/'::rational;
select '2/'::rational;
select '/2'::rational;
select 'sdfkjsdfj34984538'::rational;

-- simplification

-- double negative becomes positive
select rational_simplify('-1/-3');
-- works with negative value
select rational_simplify('-3/12');
-- dodge the INT32_MIN/-1 mistake
select rational_simplify('-2147483648/2147483647');
-- don't move negative if it would overflow
select rational_simplify('1/-2147483648');
-- biggest value reduces
select rational_simplify('2147483647/2147483647');
-- smallest value reduces
select rational_simplify('-2147483648/-2147483648');
-- idempotent on simplified expression
select rational_simplify('1/1');

-- addition

-- additive identity
select '0/1'::rational + '1/2';
-- additive inverse
select '1/2'::rational + '-1/2';
-- just regular
select '1/2'::rational + '1/2';
-- forcing intermediate simplification
select '2147483647/2147483647'::rational + '1/1';
-- overflow (sqrt(max)+1)/1 + 1/sqrt(max)
select '46342/1'::rational + '1/46341';

-- multiplication

-- multiplicative identity
select '1/1'::rational * '1/2';
-- multiplicative inverse
select '2/1'::rational * '1/2';
-- just regular
select '5/8'::rational * '3/5';
-- forcing intermediate simplification
select '2147483647/2147483647'::rational * '2/2';
-- overflow
select '46342/46341'::rational * '46341/46342';

-- division

select 1::rational / 3;
select '2/3'::rational / '2/3';

-- negation

-- flips sign of numerator
select -('1/2'::rational);
-- flips back
select -('-1/2'::rational);
-- overflow not possible
select -('-2147483648/1'::rational);
select -('1/-2147483648'::rational);
select -('-2147483648/-2147483648'::rational);

-- subtraction

-- just regular
select '1/2'::rational - '1/2';
-- can go negative
select '1/2'::rational - '1/1';
-- forcing intermediate simplification
select '2147483647/2147483647'::rational - '100/100';
-- overflow (sqrt(max)+1)/1 - 1/sqrt(max)
select '46342/1'::rational - '1/46341';

-- comparison

-- equal in every way
select '1/1'::rational = '1/1';
-- same equivalence class
select '20/40'::rational = '22/44';
-- negatives work too
select '-20/40'::rational = '-22/44';
-- overflow not possible
select '46342/46341'::rational = '46342/46341';
-- high precision
select '1/2147483647'::rational = '1/2147483646';
select '1/3'::rational * 3 = 1;
select 1.0/3.0 = 1.0;
-- not everything is equal
select '2/3'::rational = '8/5';

-- negates equality
select '1/1'::rational <> '1/1';
-- overflow not possible
select '46342/46341'::rational <> '46342/46341';
-- not equal
select '2/3'::rational <> '8/5';

-- lt anti-reflexive
select '1/2'::rational < '1/2';
-- gt anti-reflexive
select '1/2'::rational > '1/2';
-- overflow not possible
select '1/2147483647'::rational < '2/2147483647';

-- lte
select r
  from unnest(ARRAY[
      '303700050/303700050',
      '-2/1',
      '0/9999999',
      '-11/17',
      '100/1',
      '3/4',
      '-1/2',
      '-1/1',
      '5/8',
      '6/9',
      '5/8'
    ]::rational[]) as r
order by r asc;
-- gte
select r
  from unnest(ARRAY[
      '303700050/303700050',
      '-2/1',
      '0/9999999',
      '-11/17',
      '100/1',
      '3/4',
      '-1/2',
      '-1/1',
      '5/8',
      '6/9',
      '5/8'
    ]::rational[]) as r
order by r desc;

-- btree
create table rs (
  r rational
);
create index rs_r_btree on rs using btree(r);
insert into rs values ('0/7'), ('1/7'), ('2/7'), ('3/7'),
                      ('4/7'), ('5/7'), ('6/7');
set enable_seqscan=false;

explain select * from rs where r > '1/7' and r <= '10/14';
select * from rs where r > '1/7' and r <= '10/14';

set enable_seqscan=true;
drop table rs cascade;

-- hash
create table rs (
  r rational
);
create index rs_r_hash on rs using hash(r);
insert into rs values ('0/7'), ('1/7');
set enable_seqscan=false;

explain select * from rs where r = '0/1';
select * from rs where r = '0/1';
select * from rs where r = '2/7';

set enable_seqscan=true;
drop table rs cascade;

-- aggregates

select min(r)
  from unnest(ARRAY[
      '100/1',
      NULL,
      '-11/17',
      '-1/1'
    ]::rational[]) as r;

select max(r)
  from unnest(ARRAY[
      '100/1',
      NULL,
      '-11/17',
      '-1/1'
    ]::rational[]) as r;

select max(r)
  from unnest(ARRAY[
      NULL, NULL, NULL
    ]::rational[]) as r;

select rational_simplify(sum(r))
  from unnest(ARRAY[
      '1/1',  '1/2', NULL,
      '-3/2', '1/16'
    ]::rational[]) as r;

select sum(r)
  from unnest(ARRAY[
      NULL, NULL, NULL
    ]::rational[]) as r;

-- stern-brocot intermediates

-- intermediates start at 1 -- between 0 and Infinity
select rational_intermediate(NULL, NULL);
-- random example
select rational_intermediate('15/16', 1);
select rational_intermediate('15/16', 1)
  between '15/16'::rational and 1;
select rational_intermediate('44320/39365', '77200/12184');
select rational_intermediate('44320/39365', '77200/12184')
  between '44320/39365'::rational and '77200/12184';
-- unbounded upper limit produces least greater integer
select rational_intermediate('1/3', NULL);
select rational_intermediate('3/2', NULL);
-- though not the other direction
select rational_intermediate(NULL, '15/16');