-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmpz_ap_list.c
153 lines (126 loc) · 4.15 KB
/
mpz_ap_list.c
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
#include "mpz_ap_list.h"
void mpz_ap_list_insert(mpz_ap_list_t ** list, mpz_t x, mpz_t y, mpz_t z)
{
// Calculate the distance d = y - x.
mpz_t d;
mpz_init(d);
mpz_sub(d, y, x);
mpz_ap_list_t * current = * list;
if ( current == NULL || mpz_cmp(d, current->d) < 0 )
{
// Either this is the first element or the existing first element has
// a bigger distance. We have to insert the new element as first
// element.
mpz_ap_list_t * newNode;
newNode = malloc(sizeof(mpz_ap_list_t));
// Set the values.
mpz_init_set(newNode->x, x);
mpz_init_set(newNode->y, y);
mpz_init_set(newNode->z, z);
mpz_init_set(newNode->d, d);
// Insert the new node as first element into the list.
newNode->next = *list;
*list = newNode;
// Clear d and return.
mpz_clear(d);
return;
}
// Iterate through the list and search for the element that has a bigger d.
// If found we will insert a new element before the found one. If not we
// will append a new element to the list.
while (current != NULL)
{
if ( mpz_cmp(x, current->x) == 0 )
{
// If there is already an element with the same x, then we can
// assume that this arithmetic progression exists already. Therefore
// we would not change anything.
break;
}
if ( current->next == NULL )
{
// We have reached the end of the list. Therefore we have to append
// this arithmetic progression to the end of the list.
mpz_ap_list_t * newNode;
newNode = malloc(sizeof(mpz_ap_list_t));
// Set the values.
mpz_init_set(newNode->x, x);
mpz_init_set(newNode->y, y);
mpz_init_set(newNode->z, z);
mpz_init_set(newNode->d, d);
// Append the new node as last element to the list.
newNode->next = NULL;
current->next = newNode;
break;
}
if ( current->next != NULL )
{
if ( mpz_cmp(x, current->next->x) == 0 )
{
// If there is already an element with the same x, then we can
// assume that this arithmetic progression exists already.
// Therefore we would not change anything.
break;
}
if ( mpz_cmp(current->next->d, d) >= 0 )
{
// The next element in the list has a bigger distance. Therefore
// we will insert the new arithmetic progression right after
// the current one but before the next one.
mpz_ap_list_t * newNode;
newNode = malloc(sizeof(mpz_ap_list_t));
// Set the values.
mpz_init_set(newNode->x, x);
mpz_init_set(newNode->y, y);
mpz_init_set(newNode->z, z);
mpz_init_set(newNode->d, d);
// Insert the new node between the current and the next one in
// the list.
newNode->next = current->next;
current->next = newNode;
break;
}
}
current = current->next;
}
// Clear d.
mpz_clear(d);
}
void mpz_ap_list_pop(mpz_ap_list_t ** list)
{
if (*list == NULL)
{
return;
}
mpz_clear((*list)->x);
mpz_clear((*list)->y);
mpz_clear((*list)->z);
mpz_clear((*list)->d);
mpz_ap_list_t * nextNode = NULL;
nextNode = (*list)->next;
free(*list);
*list = nextNode;
}
void mpz_ap_list_clean(mpz_ap_list_t ** list)
{
while ( *list != NULL )
{
mpz_ap_list_pop(list);
}
}
void mpz_ap_list_print(mpz_ap_list_t * list)
{
mpz_ap_list_t * current = list;
while (current != NULL)
{
mpz_out_str(stdout, 10, current->x);
printf(", ");
mpz_out_str(stdout, 10, current->y);
printf(", ");
mpz_out_str(stdout, 10, current->z);
printf(" | ");
mpz_out_str(stdout, 10, current->d);
printf("\n");
current = current->next;
}
}