OSDN Git Service

Change Copyright from PostgreSQL, Inc to PostgreSQL Global Development Group.
[pg-rex/syncrep.git] / src / backend / utils / adt / arrayutils.c
1 /*-------------------------------------------------------------------------
2  *
3  * arrayutils.c
4  *        This file contains some support routines required for array functions.
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayutils.c,v 1.12 2001/01/24 19:43:13 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15
16 #include "postgres.h"
17
18 #include "utils/array.h"
19
20
21 /* Convert subscript list into linear element number (from 0) */
22 int
23 ArrayGetOffset(int n, int *dim, int *lb, int *indx)
24 {
25         int                     i,
26                                 scale = 1,
27                                 offset = 0;
28
29         for (i = n - 1; i >= 0; i--)
30         {
31                 offset += (indx[i] - lb[i]) * scale;
32                 scale *= dim[i];
33         }
34         return offset;
35 }
36
37 /* Same, but subscripts are assumed 0-based, and use a scale array
38  * instead of raw dimension data (see mda_get_prod to create scale array)
39  */
40 int
41 ArrayGetOffset0(int n, int *tup, int *scale)
42 {
43         int                     i,
44                                 lin = 0;
45
46         for (i = 0; i < n; i++)
47                 lin += tup[i] * scale[i];
48         return lin;
49 }
50
51 /* Convert array dimensions into number of elements */
52 int
53 ArrayGetNItems(int n, int *a)
54 {
55         int                     i,
56                                 ret;
57
58         if (n <= 0)
59                 return 0;
60         ret = 1;
61         for (i = 0; i < n; i++)
62                 ret *= a[i];
63         return ret;
64 }
65
66 /* Compute ranges (sub-array dimensions) for an array slice */
67 void
68 mda_get_range(int n, int *span, int *st, int *endp)
69 {
70         int                     i;
71
72         for (i = 0; i < n; i++)
73                 span[i] = endp[i] - st[i] + 1;
74 }
75
76 /* Compute products of array dimensions, ie, scale factors for subscripts */
77 void
78 mda_get_prod(int n, int *range, int *prod)
79 {
80         int                     i;
81
82         prod[n - 1] = 1;
83         for (i = n - 2; i >= 0; i--)
84                 prod[i] = prod[i + 1] * range[i + 1];
85 }
86
87 /* From products of whole-array dimensions and spans of a sub-array,
88  * compute offset distances needed to step through subarray within array
89  */
90 void
91 mda_get_offset_values(int n, int *dist, int *prod, int *span)
92 {
93         int                     i,
94                                 j;
95
96         dist[n - 1] = 0;
97         for (j = n - 2; j >= 0; j--)
98         {
99                 dist[j] = prod[j] - 1;
100                 for (i = j + 1; i < n; i++)
101                         dist[j] -= (span[i] - 1) * prod[i];
102         }
103 }
104
105 /*-----------------------------------------------------------------------------
106   generates the tuple that is lexicographically one greater than the current
107   n-tuple in "curr", with the restriction that the i-th element of "curr" is
108   less than the i-th element of "span".
109   Returns -1 if no next tuple exists, else the subscript position (0..n-1)
110   corresponding to the dimension to advance along.
111   -----------------------------------------------------------------------------
112 */
113 int
114 mda_next_tuple(int n, int *curr, int *span)
115 {
116         int                     i;
117
118         if (n <= 0)
119                 return -1;
120
121         curr[n - 1] = (curr[n - 1] + 1) % span[n - 1];
122         for (i = n - 1; i && curr[i] == 0; i--)
123                 curr[i - 1] = (curr[i - 1] + 1) % span[i - 1];
124
125         if (i)
126                 return i;
127         if (curr[0])
128                 return 0;
129
130         return -1;
131 }