Skip to content

Commit

Permalink
Add math functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
kuina committed Jun 17, 2018
1 parent fe3542d commit 72dd2c3
Show file tree
Hide file tree
Showing 7 changed files with 293 additions and 2 deletions.
3 changes: 2 additions & 1 deletion package/readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ v.2018.6.17
- 16進数リテラルの構文を「16#」から「0x」に変更
- 細かな機能追加
- list.find、list.findLastメソッドの追加
- math@knapsack、draw@filterNone、draw@filterMonotone関数の追加
- math@knapsack、math@dijkstra、math@bellmanFord、math@floydWarshall、
draw@filterNone、draw@filterMonotone関数の追加

v.2018.5.17
- 輪郭線を描画するメソッド[email protected]の追加
Expand Down
9 changes: 9 additions & 0 deletions package/sys/math.kn
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ end func
+func [d0003.knd, _knapsack] knapsack(weights: []int, values: []int, maxWeight: int, reuse: bool): int
end func

+func [d0003.knd, _dijkstra] dijkstra(nodeNum: int, fromNodes: []int, toNodes: []int, values: []int, beginNode: int): []int
end func

+func [d0003.knd, _bellmanFord] bellmanFord(nodeNum: int, fromNodes: []int, toNodes: []int, values: []int, beginNode: int): []int
end func

+func [d0003.knd, _floydWarshall] floydWarshall(nodeNum: int, fromNodes: []int, toNodes: []int, values: []int): [][]int
end func

+class Mat()
*func [d0003.knd, _matDtor, _force] _dtor()
end func
Expand Down
2 changes: 1 addition & 1 deletion src/lib_common/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ EXPORT void* _cmdLine(void)
{
int i;
void** ptr;
U8* result = (U8*)AllocMem(0x10 + sizeof(Char*) * (size_t)(num - 1));
U8* result = (U8*)AllocMem(0x10 + sizeof(void**) * (size_t)(num - 1));
((S64*)result)[0] = DefaultRefCntFunc;
((S64*)result)[1] = (S64)(num - 1);
ptr = (void**)(result + 0x10);
Expand Down
194 changes: 194 additions & 0 deletions src/lib_math/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,200 @@ EXPORT S64 _knapsack(const void* weights, const void* values, S64 max_weight, Bo
return result;
}

EXPORT void* _dijkstra(S64 node_num, const void* from_nodes, const void* to_nodes, const void* values, S64 begin_node)
{
THROWDBG(from_nodes == NULL || to_nodes == NULL || values == NULL, 0xc0000005);
THROWDBG(*(S64*)((U8*)from_nodes + 0x08) != *(S64*)((U8*)to_nodes + 0x08) || *(S64*)((U8*)to_nodes + 0x08) != *(S64*)((U8*)values + 0x08), 0xe9170006);
THROWDBG(node_num <= 0 || begin_node < 0 || node_num <= begin_node, 0xe9170006);
const S64* from_nodes2 = (S64*)((U8*)from_nodes + 0x10);
const S64* to_nodes2 = (S64*)((U8*)to_nodes + 0x10);
const S64* values2 = (S64*)((U8*)values + 0x10);
S64 len = *(S64*)((U8*)from_nodes + 0x08);
S64 i;
#if defined(DBG)
for (i = 0; i < len; i++)
THROWDBG(from_nodes2[i] < 0 || node_num <= from_nodes2[i] || to_nodes2[i] < 0 || node_num <= to_nodes2[i] || values2[i] < 0, 0xe9170006);
#endif

U8* result = (U8*)AllocMem(0x10 + sizeof(S64) * (size_t)node_num);
((S64*)result)[0] = DefaultRefCntFunc;
((S64*)result)[1] = node_num;
S64* distance = (S64*)(result + 0x10);
for (i = 0; i < node_num; i++)
distance[i] = LLONG_MAX;
distance[begin_node] = 0;

S64* heap = (S64*)AllocMem(sizeof(S64) * (2 * (size_t)(node_num * len) + 2));
int heap_cnt = 1;
heap[0] = begin_node;
heap[1] = 0;
while (heap_cnt > 0)
{
S64 item_node = heap[0];
S64 item_value = heap[1];
heap_cnt--;
heap[0] = heap[heap_cnt * 2];
heap[1] = heap[heap_cnt * 2 + 1];
{
S64 del_idx = 0;
for (; ; )
{
if ((del_idx + 1) * 2 - 1 < heap_cnt && heap[del_idx * 2 + 1] > heap[((del_idx + 1) * 2 - 1) * 2 + 1])
{
S64 tmp;
tmp = heap[del_idx * 2];
heap[del_idx * 2] = heap[((del_idx + 1) * 2 - 1) * 2];
heap[((del_idx + 1) * 2 - 1) * 2] = tmp;
tmp = heap[del_idx * 2 + 1];
heap[del_idx * 2 + 1] = heap[((del_idx + 1) * 2 - 1) * 2 + 1];
heap[((del_idx + 1) * 2 - 1) * 2 + 1] = tmp;
del_idx = (del_idx + 1) * 2 - 1;
}
else if ((del_idx + 1) * 2 < heap_cnt && heap[del_idx * 2 + 1] > heap[((del_idx + 1) * 2) * 2 + 1])
{
S64 tmp;
tmp = heap[del_idx * 2];
heap[del_idx * 2] = heap[((del_idx + 1) * 2) * 2];
heap[((del_idx + 1) * 2) * 2] = tmp;
tmp = heap[del_idx * 2 + 1];
heap[del_idx * 2 + 1] = heap[((del_idx + 1) * 2) * 2 + 1];
heap[((del_idx + 1) * 2) * 2 + 1] = tmp;
del_idx = (del_idx + 1) * 2;
}
else
break;
}
}
if (distance[item_node] < item_value)
continue;
for (i = 0; i < len; i++)
{
if (from_nodes2[i] != item_node)
continue;
if (distance[to_nodes2[i]] > distance[item_node] + values2[i])
{
distance[to_nodes2[i]] = distance[item_node] + values2[i];
heap[heap_cnt * 2] = to_nodes2[i];
heap[heap_cnt * 2 + 1] = distance[to_nodes2[i]];
{
S64 ins_idx = heap_cnt;
for (; ; )
{
if (ins_idx > 0 && heap[ins_idx * 2 + 1] < heap[(ins_idx - 1) / 2 * 2 + 1])
{
S64 tmp;
tmp = heap[ins_idx * 2];
heap[ins_idx * 2] = heap[(ins_idx - 1) / 2 * 2];
heap[(ins_idx - 1) / 2 * 2] = tmp;
tmp = heap[ins_idx * 2 + 1];
heap[ins_idx * 2 + 1] = heap[(ins_idx - 1) / 2 * 2 + 1];
heap[(ins_idx - 1) / 2 * 2 + 1] = tmp;
ins_idx = (ins_idx - 1) / 2;
}
else
break;
}
}
heap_cnt++;
}
}
}
FreeMem(heap);

return result;
}

EXPORT void* _bellmanFord(S64 node_num, const void* from_nodes, const void* to_nodes, const void* values, S64 begin_node)
{
THROWDBG(from_nodes == NULL || to_nodes == NULL || values == NULL, 0xc0000005);
THROWDBG(*(S64*)((U8*)from_nodes + 0x08) != *(S64*)((U8*)to_nodes + 0x08) || *(S64*)((U8*)to_nodes + 0x08) != *(S64*)((U8*)values + 0x08), 0xe9170006);
THROWDBG(node_num <= 0 || begin_node < 0 || node_num <= begin_node, 0xe9170006);
const S64* from_nodes2 = (S64*)((U8*)from_nodes + 0x10);
const S64* to_nodes2 = (S64*)((U8*)to_nodes + 0x10);
const S64* values2 = (S64*)((U8*)values + 0x10);
S64 len = *(S64*)((U8*)from_nodes + 0x08);
S64 i;
#if defined(DBG)
for (i = 0; i < len; i++)
THROWDBG(from_nodes2[i] < 0 || node_num <= from_nodes2[i] || to_nodes2[i] < 0 || node_num <= to_nodes2[i], 0xe9170006);
#endif

U8* result = (U8*)AllocMem(0x10 + sizeof(S64) * (size_t)node_num);
((S64*)result)[0] = DefaultRefCntFunc;
((S64*)result)[1] = node_num;
S64* distance = (S64*)(result + 0x10);
for (i = 0; i < node_num; i++)
distance[i] = LLONG_MAX;
distance[begin_node] = 0;

Bool found;
do
{
found = False;
for (i = 0; i < len; i++)
{
S64 from_distance = distance[from_nodes2[i]];
if (from_distance != LLONG_MAX && distance[to_nodes2[i]] > from_distance + values2[i])
{
distance[to_nodes2[i]] = from_distance + values2[i];
found = True;
}
}
} while (found);
return result;
}

EXPORT void* _floydWarshall(S64 node_num, const void* from_nodes, const void* to_nodes, const void* values)
{
THROWDBG(from_nodes == NULL || to_nodes == NULL || values == NULL, 0xc0000005);
THROWDBG(*(S64*)((U8*)from_nodes + 0x08) != *(S64*)((U8*)to_nodes + 0x08) || *(S64*)((U8*)to_nodes + 0x08) != *(S64*)((U8*)values + 0x08), 0xe9170006);
THROWDBG(node_num <= 0, 0xe9170006);
const S64* from_nodes2 = (S64*)((U8*)from_nodes + 0x10);
const S64* to_nodes2 = (S64*)((U8*)to_nodes + 0x10);
const S64* values2 = (S64*)((U8*)values + 0x10);
S64 len = *(S64*)((U8*)from_nodes + 0x08);
S64 i, j, k;
#if defined(DBG)
for (i = 0; i < len; i++)
THROWDBG(from_nodes2[i] < 0 || node_num <= from_nodes2[i] || to_nodes2[i] < 0 || node_num <= to_nodes2[i], 0xe9170006);
#endif

U8* result = (U8*)AllocMem(0x10 + sizeof(void**) * (size_t)node_num);
((S64*)result)[0] = DefaultRefCntFunc;
((S64*)result)[1] = node_num;
void** ptr = (void**)(result + 0x10);
for (i = 0; i < node_num; i++)
{
void* item = AllocMem(0x10 + sizeof(S64) * (size_t)node_num);
((S64*)item)[0] = 1;
((S64*)item)[1] = node_num;
S64* ptr2 = (S64*)item + 2;
for (j = 0; j < node_num; j++)
ptr2[j] = i == j ? 0 : LLONG_MAX;
ptr[i] = item;
}
for (i = 0; i < len; i++)
((S64*)ptr[from_nodes2[i]] + 2)[to_nodes2[i]] = values2[i];
for (i = 0; i < node_num; i++)
{
for (j = 0; j < node_num; j++)
{
for (k = 0; k < node_num; k++)
{
S64 a = ((S64*)ptr[j] + 2)[i];
S64 b = ((S64*)ptr[i] + 2)[k];
if (a == LLONG_MAX || b == LLONG_MAX)
continue;
S64 value = a + b;
if (((S64*)ptr[j] + 2)[k] > value)
((S64*)ptr[j] + 2)[k] = value;
}
}
}

return result;
}

EXPORT SClass* _makeMat(SClass* me_, S64 row, S64 col)
{
THROWDBG(row <= 0 || col <= 0, 0xe9170006);
Expand Down
3 changes: 3 additions & 0 deletions src/lib_math/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@ EXPORT double _gamma(double n);
EXPORT double _fact(double n);
EXPORT S64 _factInt(S64 n);
EXPORT S64 _knapsack(const void* weights, const void* values, S64 max_weight, Bool reuse);
EXPORT void* _dijkstra(S64 node_num, const void* from_nodes, const void* to_nodes, const void* values, S64 begin_node);
EXPORT void* _bellmanFord(S64 node_num, const void* from_nodes, const void* to_nodes, const void* values, S64 begin_node);
EXPORT void* _floydWarshall(S64 node_num, const void* from_nodes, const void* to_nodes, const void* values);
EXPORT SClass* _makeMat(SClass* me_, S64 row, S64 col);
EXPORT void _matDtor(SClass* me_);
63 changes: 63 additions & 0 deletions test/correct/log0021.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,27 @@ Excpt: 80000003
> Not found.
> 7
> 10
> 0
> 2
> 5
> 7
> 11
> 8
> 16
> 0
> 2
> 5
> 7
> 11
> 8
> 16
> 0
> 2
> 5
> 7
> 11
> 8
> 16
> 3
> 5
> Not found.
Expand All @@ -16,6 +37,27 @@ Excpt: 80000003
> Not found.
> 7
> 10
> 0
> 2
> 5
> 7
> 11
> 8
> 16
> 0
> 2
> 5
> 7
> 11
> 8
> 16
> 0
> 2
> 5
> 7
> 11
> 8
> 16
> 3
> 5
> Not found.
Expand All @@ -24,4 +66,25 @@ Excpt: 80000003
> Not found.
> 7
> 10
> 0
> 2
> 5
> 7
> 11
> 8
> 16
> 0
> 2
> 5
> 7
> 11
> 8
> 16
> 0
> 2
> 5
> 7
> 11
> 8
> 16
end: ../../test/output/output0021.exe
21 changes: 21 additions & 0 deletions test/kn/test0021.kn
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,26 @@ func main()
do cui@print(math@knapsack([2, 1, 3, 2], [3, 2, 4, 2], 5, false).toStr())
do cui@print(math@knapsack([3, 4, 2], [4, 5, 3], 7, true).toStr())
end block

block
var d: []int :: math@dijkstra(7, [0, 1, 0, 2, 1, 2, 1, 3, 2, 3, 1, 4, 4, 5, 3, 5, 4, 6, 5, 6], [1, 0, 2, 0, 2, 1, 3, 1, 3, 2, 4, 1, 5, 4, 5, 3, 6, 4, 6, 5], [2, 2, 5, 5, 4, 4, 6, 6, 2, 2, 10, 10, 3, 3, 1, 1, 5, 5, 9, 9], 0)
for i(0, ^d - 1)
do cui@print(d[i].toStr())
end for
end block

block
var d: []int :: math@bellmanFord(7, [0, 1, 0, 2, 1, 2, 1, 3, 2, 3, 1, 4, 4, 5, 3, 5, 4, 6, 5, 6], [1, 0, 2, 0, 2, 1, 3, 1, 3, 2, 4, 1, 5, 4, 5, 3, 6, 4, 6, 5], [2, 2, 5, 5, 4, 4, 6, 6, 2, 2, 10, 10, 3, 3, 1, 1, 5, 5, 9, 9], 0)
for i(0, ^d - 1)
do cui@print(d[i].toStr())
end for
end block

block
var d: [][]int :: math@floydWarshall(7, [0, 1, 0, 2, 1, 2, 1, 3, 2, 3, 1, 4, 4, 5, 3, 5, 4, 6, 5, 6], [1, 0, 2, 0, 2, 1, 3, 1, 3, 2, 4, 1, 5, 4, 5, 3, 6, 4, 6, 5], [2, 2, 5, 5, 4, 4, 6, 6, 2, 2, 10, 10, 3, 3, 1, 1, 5, 5, 9, 9])
for i(0, ^d - 1)
do cui@print(d[0][i].toStr())
end for
end block
end for
end func

0 comments on commit 72dd2c3

Please sign in to comment.