Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
001f9d04
提交
001f9d04
authored
7月 03, 2010
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
The MultiDimension tools was extended with a few helper methods. The API was unified a bit.
上级
725532f8
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
265 行增加
和
70 行删除
+265
-70
changelog.html
h2/src/docsrc/html/changelog.html
+3
-1
MultiDimension.java
h2/src/main/org/h2/tools/MultiDimension.java
+85
-54
TestMultiDimension.java
h2/src/test/org/h2/test/db/TestMultiDimension.java
+177
-15
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
001f9d04
...
@@ -18,7 +18,9 @@ Change Log
...
@@ -18,7 +18,9 @@ Change Log
<h1>
Change Log
</h1>
<h1>
Change Log
</h1>
<h2>
Next Version (unreleased)
</h2>
<h2>
Next Version (unreleased)
</h2>
<ul><li>
ODBC: additional connection settings can now be added to the database name.
<ul><li>
The MultiDimension tools was extended with a few helper methods.
The API was unified a bit.
</li><li>
ODBC: additional connection settings can now be added to the database name.
Example: ~/test;cipher=xtea. Therefore, encrypted databases are supported.
Example: ~/test;cipher=xtea. Therefore, encrypted databases are supported.
</li><li>
Local temporary tables can now be created without having to commit a transaction
</li><li>
Local temporary tables can now be created without having to commit a transaction
using CREATE LOCAL TEMPORARY TABLE TEMP(ID INT PRIMARY KEY) TRANSACTIONAL.
using CREATE LOCAL TEMPORARY TABLE TEMP(ID INT PRIMARY KEY) TRANSACTIONAL.
...
...
h2/src/main/org/h2/tools/MultiDimension.java
浏览文件 @
001f9d04
...
@@ -37,65 +37,107 @@ public class MultiDimension implements Comparator<long[]> {
...
@@ -37,65 +37,107 @@ public class MultiDimension implements Comparator<long[]> {
return
INSTANCE
;
return
INSTANCE
;
}
}
/**
* Normalize a value so that it is between the minimum and maximum value for
* the given number of dimensions.
*
* @param dimensions the number of dimensions
* @param value the value (must be in the range min..max)
* @param min the minimum value
* @param max the maximum value (must be larger than min)
* @return the normalized value in the range 0..getMaxValue(dimensions)
*/
public
int
normalize
(
int
dimensions
,
double
value
,
double
min
,
double
max
)
{
if
(
value
<
min
||
value
>
max
)
{
throw
new
IllegalArgumentException
(
min
+
"<"
+
value
+
"<"
+
max
);
}
double
x
=
(
value
-
min
)
/
(
max
-
min
);
return
(
int
)
(
x
*
getMaxValue
(
dimensions
));
}
/**
* Get the maximum value for the given dimension count. For two dimensions,
* each value must contain at most 32 bit, for 3: 21 bit, 4: 16 bit, 5: 12
* bit, 6: 10 bit, 7: 9 bit, 8: 8 bit.
*
* @param dimensions the number of dimensions
* @return the maximum value
*/
public
int
getMaxValue
(
int
dimensions
)
{
if
(
dimensions
<
2
||
dimensions
>
32
)
{
throw
new
IllegalArgumentException
(
""
+
dimensions
);
}
int
bitsPerValue
=
getBitsPerValue
(
dimensions
);
return
(
int
)
((
1L
<<
bitsPerValue
)
-
1
);
}
private
int
getBitsPerValue
(
int
dimensions
)
{
return
Math
.
min
(
31
,
64
/
dimensions
);
}
/**
/**
* Convert the multi-dimensional value into a one-dimensional (scalar) value.
* Convert the multi-dimensional value into a one-dimensional (scalar) value.
* This is done by interleaving the bits of the values.
* This is done by interleaving the bits of the values.
* Each values must be b
igger or equal to 0. T
he maximum value
* Each values must be b
etween 0 (including) and t
he maximum value
*
depends on the number of dimensions. For two keys, it is 32 bit,
*
for the given number of dimensions (getMaxValue, excluding).
*
for 3: 21 bit, 4: 16 bit, 5: 12 bit, 6: 10 bit, 7: 9 bit, 8: 8 bit
.
*
To normalize values to this range, use the normalize function
.
*
*
* @param values the multi-dimensional value
* @param values the multi-dimensional value
* @return the scalar value
* @return the scalar value
*/
*/
public
long
interleave
(
int
[]
values
)
{
public
long
interleave
(
int
...
values
)
{
int
dimensions
=
values
.
length
;
int
dimensions
=
values
.
length
;
int
bitsPerValue
=
64
/
dimensions
;
// for 2 keys: 0x800000; 3: 0x
long
max
=
getMaxValue
(
dimensions
);
long
max
=
getMaxValue
(
dimensions
);
int
bitsPerValue
=
getBitsPerValue
(
dimensions
);
long
x
=
0
;
long
x
=
0
;
for
(
int
i
=
0
;
i
<
dimensions
;
i
++)
{
for
(
int
i
=
0
;
i
<
dimensions
;
i
++)
{
long
k
=
values
[
i
];
long
k
=
values
[
i
];
if
(
k
<
0
||
k
>
=
max
)
{
if
(
k
<
0
||
k
>
max
)
{
throw
new
IllegalArgumentException
(
"value out of range; value="
+
values
[
i
]
+
" min=0 max=
"
+
max
);
throw
new
IllegalArgumentException
(
0
+
"<"
+
k
+
"<
"
+
max
);
}
}
for
(
int
b
=
0
;
b
<
bitsPerValue
;
b
++)
{
for
(
int
b
=
0
;
b
<
bitsPerValue
;
b
++)
{
x
|=
(
k
&
(
1L
<<
b
))
<<
(
i
+
(
dimensions
-
1
)
*
b
);
x
|=
(
k
&
(
1L
<<
b
))
<<
(
i
+
(
dimensions
-
1
)
*
b
);
}
}
}
}
if
(
dimensions
==
2
)
{
long
xx
=
getMorton2
(
values
[
0
],
values
[
1
]);
if
(
xx
!=
x
)
{
throw
new
IllegalArgumentException
(
"test"
);
}
}
return
x
;
return
x
;
}
}
/**
/**
* Get the maximum value for the given dimension count
* Convert the two-dimensional value into a one-dimensional (scalar) value.
* @param dimensions the number of dimensions
* This is done by interleaving the bits of the values.
* Each values must be between 0 (including) and the maximum value
* for the given number of dimensions (getMaxValue, excluding).
* To normalize values to this range, use the normalize function.
*
*
* @return the maximum value
* @param x the value of the first dimension, normalized
* @param y the value of the second dimension, normalized
* @return the scalar value
*/
*/
public
static
long
getMaxValue
(
int
dimensions
)
{
public
long
interleave
(
int
x
,
int
y
)
{
if
(
dimensions
<
2
||
dimensions
>
64
)
{
if
(
x
<
0
)
{
throw
new
IllegalArgumentException
(
"dimensions: "
+
dimensions
);
throw
new
IllegalArgumentException
(
0
+
"<"
+
x
);
}
if
(
y
<
0
)
{
throw
new
IllegalArgumentException
(
0
+
"<"
+
y
);
}
long
z
=
0
;
for
(
int
i
=
0
;
i
<
32
;
i
++)
{
z
|=
(
x
&
(
1L
<<
i
))
<<
i
;
z
|=
(
y
&
(
1L
<<
i
))
<<
(
i
+
1
);
}
}
int
bitsPerValue
=
64
/
dimensions
;
return
z
;
// for 2 keys: 0x800000; 3: 0x
return
1L
<<
bitsPerValue
;
}
}
/**
/**
* Gets one of the original multi-dimensional values from a scalar value.
* Gets one of the original multi-dimensional values from a scalar value.
*
*
* @param scalar the scalar value
* @param dimensions the number of dimensions
* @param dimensions the number of dimensions
* @param scalar the scalar value
* @param dim the dimension of the returned value (starting from 0)
* @param dim the dimension of the returned value (starting from 0)
* @return the value
* @return the value
*/
*/
public
int
deinterleave
(
long
scalar
,
int
dimensions
,
int
dim
)
{
public
int
deinterleave
(
int
dimensions
,
long
scalar
,
int
dim
)
{
int
bitsPerValue
=
64
/
dimensions
;
int
bitsPerValue
=
getBitsPerValue
(
dimensions
)
;
int
value
=
0
;
int
value
=
0
;
for
(
int
i
=
0
;
i
<
bitsPerValue
;
i
++)
{
for
(
int
i
=
0
;
i
<
bitsPerValue
;
i
++)
{
value
|=
(
scalar
>>
(
dim
+
(
dimensions
-
1
)
*
i
))
&
(
1L
<<
i
);
value
|=
(
scalar
>>
(
dim
+
(
dimensions
-
1
)
*
i
))
&
(
1L
<<
i
);
...
@@ -103,14 +145,6 @@ public class MultiDimension implements Comparator<long[]> {
...
@@ -103,14 +145,6 @@ public class MultiDimension implements Comparator<long[]> {
return
value
;
return
value
;
}
}
// public static int get(long z, int d) {
// int n = 0;
// for (int i = 0; i < 31; i++) {
// n |= (z & (1 << (i + i + d))) >> (i + d);
// }
// return n;
// }
/**
/**
* Generates an optimized multi-dimensional range query.
* Generates an optimized multi-dimensional range query.
* The query contains parameters. It can only be used with the H2 database.
* The query contains parameters. It can only be used with the H2 database.
...
@@ -172,7 +206,7 @@ public class MultiDimension implements Comparator<long[]> {
...
@@ -172,7 +206,7 @@ public class MultiDimension implements Comparator<long[]> {
private
long
[][]
getMortonRanges
(
int
[]
min
,
int
[]
max
)
{
private
long
[][]
getMortonRanges
(
int
[]
min
,
int
[]
max
)
{
int
len
=
min
.
length
;
int
len
=
min
.
length
;
if
(
max
.
length
!=
len
)
{
if
(
max
.
length
!=
len
)
{
throw
new
IllegalArgumentException
(
"dimensions mismatch"
);
throw
new
IllegalArgumentException
(
len
+
"="
+
max
.
length
);
}
}
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
if
(
min
[
i
]
>
max
[
i
])
{
if
(
min
[
i
]
>
max
[
i
])
{
...
@@ -184,21 +218,12 @@ public class MultiDimension implements Comparator<long[]> {
...
@@ -184,21 +218,12 @@ public class MultiDimension implements Comparator<long[]> {
int
total
=
getSize
(
min
,
max
,
len
);
int
total
=
getSize
(
min
,
max
,
len
);
ArrayList
<
long
[]>
list
=
New
.
arrayList
();
ArrayList
<
long
[]>
list
=
New
.
arrayList
();
addMortonRanges
(
list
,
min
,
max
,
len
,
0
);
addMortonRanges
(
list
,
min
,
max
,
len
,
0
);
optimize
(
list
,
total
);
combineEntries
(
list
,
total
);
long
[][]
ranges
=
new
long
[
list
.
size
()][
2
];
long
[][]
ranges
=
new
long
[
list
.
size
()][
2
];
list
.
toArray
(
ranges
);
list
.
toArray
(
ranges
);
return
ranges
;
return
ranges
;
}
}
private
long
getMorton2
(
int
x
,
int
y
)
{
long
z
=
0
;
for
(
int
i
=
0
;
i
<
32
;
i
++)
{
z
|=
(
x
&
(
1L
<<
i
))
<<
i
;
z
|=
(
y
&
(
1L
<<
i
))
<<
(
i
+
1
);
}
return
z
;
}
private
int
getSize
(
int
[]
min
,
int
[]
max
,
int
len
)
{
private
int
getSize
(
int
[]
min
,
int
[]
max
,
int
len
)
{
int
size
=
1
;
int
size
=
1
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
...
@@ -208,9 +233,15 @@ public class MultiDimension implements Comparator<long[]> {
...
@@ -208,9 +233,15 @@ public class MultiDimension implements Comparator<long[]> {
return
size
;
return
size
;
}
}
private
void
optimize
(
ArrayList
<
long
[]>
list
,
int
total
)
{
/**
* Combine entries if the size of the list is too large.
*
* @param list the size of the list
* @param total
*/
private
void
combineEntries
(
ArrayList
<
long
[]>
list
,
int
total
)
{
Collections
.
sort
(
list
,
this
);
Collections
.
sort
(
list
,
this
);
for
(
int
minGap
=
10
;;
minGap
+=
minGap
/
2
)
{
for
(
int
minGap
=
10
;
minGap
<
total
;
minGap
+=
minGap
/
2
)
{
for
(
int
i
=
0
;
i
<
list
.
size
()
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
list
.
size
()
-
1
;
i
++)
{
long
[]
current
=
list
.
get
(
i
);
long
[]
current
=
list
.
get
(
i
);
long
[]
next
=
list
.
get
(
i
+
1
);
long
[]
next
=
list
.
get
(
i
+
1
);
...
@@ -224,9 +255,9 @@ public class MultiDimension implements Comparator<long[]> {
...
@@ -224,9 +255,9 @@ public class MultiDimension implements Comparator<long[]> {
for
(
long
[]
range
:
list
)
{
for
(
long
[]
range
:
list
)
{
searched
+=
range
[
1
]
-
range
[
0
]
+
1
;
searched
+=
range
[
1
]
-
range
[
0
]
+
1
;
}
}
if
(
searched
>
2
*
total
||
list
.
size
()
<
3
/* || minGap > total */
)
{
if
(
searched
>
2
*
total
||
list
.
size
()
<
100
)
{
break
;
break
;
}
}
}
}
}
}
...
@@ -236,18 +267,18 @@ public class MultiDimension implements Comparator<long[]> {
...
@@ -236,18 +267,18 @@ public class MultiDimension implements Comparator<long[]> {
private
void
addMortonRanges
(
ArrayList
<
long
[]>
list
,
int
[]
min
,
int
[]
max
,
int
len
,
int
level
)
{
private
void
addMortonRanges
(
ArrayList
<
long
[]>
list
,
int
[]
min
,
int
[]
max
,
int
len
,
int
level
)
{
if
(
level
>
100
)
{
if
(
level
>
100
)
{
throw
new
IllegalArgumentException
(
"
Stop"
);
throw
new
IllegalArgumentException
(
"
"
+
level
);
}
}
int
largest
=
0
,
largestDiff
=
0
;
int
largest
=
0
,
largestDiff
=
0
;
long
size
=
1
;
long
size
=
1
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
int
diff
=
max
[
i
]
-
min
[
i
];
int
diff
=
max
[
i
]
-
min
[
i
];
if
(
diff
<
0
)
{
if
(
diff
<
0
)
{
throw
new
IllegalArgumentException
(
"
Stop"
);
throw
new
IllegalArgumentException
(
"
"
+
diff
);
}
}
size
*=
diff
+
1
;
size
*=
diff
+
1
;
if
(
size
<
0
)
{
if
(
size
<
0
)
{
throw
new
IllegalArgumentException
(
"
Stop"
);
throw
new
IllegalArgumentException
(
"
"
+
size
);
}
}
if
(
diff
>
largestDiff
)
{
if
(
diff
>
largestDiff
)
{
largestDiff
=
diff
;
largestDiff
=
diff
;
...
@@ -256,7 +287,7 @@ public class MultiDimension implements Comparator<long[]> {
...
@@ -256,7 +287,7 @@ public class MultiDimension implements Comparator<long[]> {
}
}
long
low
=
interleave
(
min
),
high
=
interleave
(
max
);
long
low
=
interleave
(
min
),
high
=
interleave
(
max
);
if
(
high
<
low
)
{
if
(
high
<
low
)
{
throw
new
IllegalArgumentException
(
"Stop"
);
throw
new
IllegalArgumentException
(
high
+
"<"
+
low
);
}
}
long
range
=
high
-
low
+
1
;
long
range
=
high
-
low
+
1
;
if
(
range
==
size
)
{
if
(
range
==
size
)
{
...
@@ -294,7 +325,7 @@ public class MultiDimension implements Comparator<long[]> {
...
@@ -294,7 +325,7 @@ public class MultiDimension implements Comparator<long[]> {
scale
--;
scale
--;
int
m
=
roundUp
(
a
+
2
,
1
<<
scale
)
-
1
;
int
m
=
roundUp
(
a
+
2
,
1
<<
scale
)
-
1
;
if
(
m
<=
a
||
m
>=
b
)
{
if
(
m
<=
a
||
m
>=
b
)
{
throw
new
IllegalArgumentException
(
"stop"
);
throw
new
IllegalArgumentException
(
a
+
"<"
+
m
+
"<"
+
b
);
}
}
return
m
;
return
m
;
}
}
...
...
h2/src/test/org/h2/test/db/TestMultiDimension.java
浏览文件 @
001f9d04
差异被折叠。
点击展开。
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论