OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [testsuite/] [go.test/] [test/] [bench/] [shootout/] [meteor-contest.c] - Blame information for rev 700

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 700 jeremybenn
/*
2
Redistribution and use in source and binary forms, with or without
3
modification, are permitted provided that the following conditions are met:
4
 
5
    * Redistributions of source code must retain the above copyright
6
    notice, this list of conditions and the following disclaimer.
7
 
8
    * Redistributions in binary form must reproduce the above copyright
9
    notice, this list of conditions and the following disclaimer in the
10
    documentation and/or other materials provided with the distribution.
11
 
12
    * Neither the name of "The Computer Language Benchmarks Game" nor the
13
    name of "The Computer Language Shootout Benchmarks" nor the names of
14
    its contributors may be used to endorse or promote products derived
15
    from this software without specific prior written permission.
16
 
17
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
POSSIBILITY OF SUCH DAMAGE.
28
*/
29
 
30
/* The Computer Language Benchmarks Game
31
 * http://shootout.alioth.debian.org/
32
 *
33
 * contributed by Christian Vosteen
34
 */
35
 
36
#include <stdlib.h>
37
#include <stdio.h>
38
#define TRUE 1
39
#define FALSE 0
40
 
41
/* The board is a 50 cell hexagonal pattern.  For    . . . . .
42
 * maximum speed the board will be implemented as     . . . . .
43
 * 50 bits, which will fit into a 64 bit long long   . . . . .
44
 * int.                                               . . . . .
45
 *                                                   . . . . .
46
 * I will represent 0's as empty cells and 1's        . . . . .
47
 * as full cells.                                    . . . . .
48
 *                                                    . . . . .
49
 *                                                   . . . . .
50
 *                                                    . . . . .
51
 */
52
 
53
unsigned long long board = 0xFFFC000000000000ULL;
54
 
55
/* The puzzle pieces must be specified by the path followed
56
 * from one end to the other along 12 hexagonal directions.
57
 *
58
 *   Piece 0   Piece 1   Piece 2   Piece 3   Piece 4
59
 *
60
 *  O O O O    O   O O   O O O     O O O     O   O
61
 *         O    O O           O       O       O O
62
 *                           O         O         O
63
 *
64
 *   Piece 5   Piece 6   Piece 7   Piece 8   Piece 9
65
 *
66
 *    O O O     O O       O O     O O        O O O O
67
 *       O O       O O       O       O O O        O
68
 *                  O       O O
69
 *
70
 * I had to make it 12 directions because I wanted all of the
71
 * piece definitions to fit into the same size arrays.  It is
72
 * not possible to define piece 4 in terms of the 6 cardinal
73
 * directions in 4 moves.
74
 */
75
 
76
#define E     0
77
#define ESE   1
78
#define SE    2
79
#define S     3
80
#define SW    4
81
#define WSW   5
82
#define W     6
83
#define WNW   7
84
#define NW    8
85
#define N     9
86
#define NE    10
87
#define ENE   11
88
#define PIVOT 12
89
 
90
char piece_def[10][4] = {
91
   {  E,  E,  E, SE},
92
   { SE,  E, NE,  E},
93
   {  E,  E, SE, SW},
94
   {  E,  E, SW, SE},
95
   { SE,  E, NE,  S},
96
   {  E,  E, SW,  E},
97
   {  E, SE, SE, NE},
98
   {  E, SE, SE,  W},
99
   {  E, SE,  E,  E},
100
   {  E,  E,  E, SW}
101
};
102
 
103
 
104
/* To minimize the amount of work done in the recursive solve function below,
105
 * I'm going to allocate enough space for all legal rotations of each piece
106
 * at each position on the board. That's 10 pieces x 50 board positions x
107
 * 12 rotations.  However, not all 12 rotations will fit on every cell, so
108
 * I'll have to keep count of the actual number that do.
109
 * The pieces are going to be unsigned long long ints just like the board so
110
 * they can be bitwise-anded with the board to determine if they fit.
111
 * I'm also going to record the next possible open cell for each piece and
112
 * location to reduce the burden on the solve function.
113
 */
114
unsigned long long pieces[10][50][12];
115
int piece_counts[10][50];
116
char next_cell[10][50][12];
117
 
118
/* Returns the direction rotated 60 degrees clockwise */
119
char rotate(char dir) {
120
   return (dir + 2) % PIVOT;
121
}
122
 
123
/* Returns the direction flipped on the horizontal axis */
124
char flip(char dir) {
125
   return (PIVOT - dir) % PIVOT;
126
}
127
 
128
 
129
/* Returns the new cell index from the specified cell in the
130
 * specified direction.  The index is only valid if the
131
 * starting cell and direction have been checked by the
132
 * out_of_bounds function first.
133
 */
134
char shift(char cell, char dir) {
135
   switch(dir) {
136
      case E:
137
         return cell + 1;
138
      case ESE:
139
         if((cell / 5) % 2)
140
            return cell + 7;
141
         else
142
            return cell + 6;
143
      case SE:
144
         if((cell / 5) % 2)
145
            return cell + 6;
146
         else
147
            return cell + 5;
148
      case S:
149
         return cell + 10;
150
      case SW:
151
         if((cell / 5) % 2)
152
            return cell + 5;
153
         else
154
            return cell + 4;
155
      case WSW:
156
         if((cell / 5) % 2)
157
            return cell + 4;
158
         else
159
            return cell + 3;
160
      case W:
161
         return cell - 1;
162
      case WNW:
163
         if((cell / 5) % 2)
164
            return cell - 6;
165
         else
166
            return cell - 7;
167
      case NW:
168
         if((cell / 5) % 2)
169
            return cell - 5;
170
         else
171
            return cell - 6;
172
      case N:
173
         return cell - 10;
174
      case NE:
175
         if((cell / 5) % 2)
176
            return cell - 4;
177
         else
178
            return cell - 5;
179
      case ENE:
180
         if((cell / 5) % 2)
181
            return cell - 3;
182
         else
183
            return cell - 4;
184
      default:
185
         return cell;
186
   }
187
}
188
 
189
/* Returns wether the specified cell and direction will land outside
190
 * of the board.  Used to determine if a piece is at a legal board
191
 * location or not.
192
 */
193
char out_of_bounds(char cell, char dir) {
194
   char i;
195
   switch(dir) {
196
      case E:
197
         return cell % 5 == 4;
198
      case ESE:
199
         i = cell % 10;
200
         return i == 4 || i == 8 || i == 9 || cell >= 45;
201
      case SE:
202
         return cell % 10 == 9 || cell >= 45;
203
      case S:
204
         return cell >= 40;
205
      case SW:
206
         return cell % 10 == 0 || cell >= 45;
207
      case WSW:
208
         i = cell % 10;
209
         return i == 0 || i == 1 || i == 5 || cell >= 45;
210
      case W:
211
         return cell % 5 == 0;
212
      case WNW:
213
         i = cell % 10;
214
         return i == 0 || i == 1 || i == 5 || cell < 5;
215
      case NW:
216
         return cell % 10 == 0 || cell < 5;
217
      case N:
218
         return cell < 10;
219
      case NE:
220
         return cell % 10 == 9 || cell < 5;
221
      case ENE:
222
         i = cell % 10;
223
         return i == 4 || i == 8 || i == 9 || cell < 5;
224
      default:
225
         return FALSE;
226
   }
227
}
228
 
229
/* Rotate a piece 60 degrees clockwise */
230
void rotate_piece(int piece) {
231
   int i;
232
   for(i = 0; i < 4; i++)
233
      piece_def[piece][i] = rotate(piece_def[piece][i]);
234
}
235
 
236
/* Flip a piece along the horizontal axis */
237
void flip_piece(int piece) {
238
   int i;
239
   for(i = 0; i < 4; i++)
240
      piece_def[piece][i] = flip(piece_def[piece][i]);
241
}
242
 
243
/* Convenience function to quickly calculate all of the indices for a piece */
244
void calc_cell_indices(char *cell, int piece, char index) {
245
   cell[0] = index;
246
   cell[1] = shift(cell[0], piece_def[piece][0]);
247
   cell[2] = shift(cell[1], piece_def[piece][1]);
248
   cell[3] = shift(cell[2], piece_def[piece][2]);
249
   cell[4] = shift(cell[3], piece_def[piece][3]);
250
}
251
 
252
/* Convenience function to quickly calculate if a piece fits on the board */
253
int cells_fit_on_board(char *cell, int piece) {
254
   return (!out_of_bounds(cell[0], piece_def[piece][0]) &&
255
         !out_of_bounds(cell[1], piece_def[piece][1]) &&
256
         !out_of_bounds(cell[2], piece_def[piece][2]) &&
257
         !out_of_bounds(cell[3], piece_def[piece][3]));
258
}
259
 
260
/* Returns the lowest index of the cells of a piece.
261
 * I use the lowest index that a piece occupies as the index for looking up
262
 * the piece in the solve function.
263
 */
264
char minimum_of_cells(char *cell) {
265
   char minimum = cell[0];
266
   minimum = cell[1] < minimum ? cell[1] : minimum;
267
   minimum = cell[2] < minimum ? cell[2] : minimum;
268
   minimum = cell[3] < minimum ? cell[3] : minimum;
269
   minimum = cell[4] < minimum ? cell[4] : minimum;
270
   return minimum;
271
}
272
 
273
/* Calculate the lowest possible open cell if the piece is placed on the board.
274
 * Used to later reduce the amount of time searching for open cells in the
275
 * solve function.
276
 */
277
char first_empty_cell(char *cell, char minimum) {
278
   char first_empty = minimum;
279
   while(first_empty == cell[0] || first_empty == cell[1] ||
280
         first_empty == cell[2] || first_empty == cell[3] ||
281
         first_empty == cell[4])
282
      first_empty++;
283
   return first_empty;
284
}
285
 
286
/* Generate the unsigned long long int that will later be anded with the
287
 * board to determine if it fits.
288
 */
289
unsigned long long bitmask_from_cells(char *cell) {
290
   unsigned long long piece_mask = 0ULL;
291
   int i;
292
   for(i = 0; i < 5; i++)
293
      piece_mask |= 1ULL << cell[i];
294
   return piece_mask;
295
}
296
 
297
/* Record the piece and other important information in arrays that will
298
 * later be used by the solve function.
299
 */
300
void record_piece(int piece, int minimum, char first_empty,
301
      unsigned long long piece_mask) {
302
   pieces[piece][minimum][piece_counts[piece][minimum]] = piece_mask;
303
   next_cell[piece][minimum][piece_counts[piece][minimum]] = first_empty;
304
   piece_counts[piece][minimum]++;
305
}
306
 
307
 
308
/* Fill the entire board going cell by cell.  If any cells are "trapped"
309
 * they will be left alone.
310
 */
311
void fill_contiguous_space(char *board, int index) {
312
   if(board[index] == 1)
313
      return;
314
   board[index] = 1;
315
   if(!out_of_bounds(index, E))
316
      fill_contiguous_space(board, shift(index, E));
317
   if(!out_of_bounds(index, SE))
318
      fill_contiguous_space(board, shift(index, SE));
319
   if(!out_of_bounds(index, SW))
320
      fill_contiguous_space(board, shift(index, SW));
321
   if(!out_of_bounds(index, W))
322
      fill_contiguous_space(board, shift(index, W));
323
   if(!out_of_bounds(index, NW))
324
      fill_contiguous_space(board, shift(index, NW));
325
   if(!out_of_bounds(index, NE))
326
      fill_contiguous_space(board, shift(index, NE));
327
}
328
 
329
 
330
/* To thin the number of pieces, I calculate if any of them trap any empty
331
 * cells at the edges.  There are only a handful of exceptions where the
332
 * the board can be solved with the trapped cells.  For example:  piece 8 can
333
 * trap 5 cells in the corner, but piece 3 can fit in those cells, or piece 0
334
 * can split the board in half where both halves are viable.
335
 */
336
int has_island(char *cell, int piece) {
337
   char temp_board[50];
338
   char c;
339
   int i;
340
   for(i = 0; i < 50; i++)
341
      temp_board[i] = 0;
342
   for(i = 0; i < 5; i++)
343
      temp_board[((int)cell[i])] = 1;
344
   i = 49;
345
   while(temp_board[i] == 1)
346
      i--;
347
   fill_contiguous_space(temp_board, i);
348
   c = 0;
349
   for(i = 0; i < 50; i++)
350
      if(temp_board[i] == 0)
351
         c++;
352
   if(c == 0 || (c == 5 && piece == 8) || (c == 40 && piece == 8) ||
353
         (c % 5 == 0 && piece == 0))
354
      return FALSE;
355
   else
356
      return TRUE;
357
}
358
 
359
 
360
/* Calculate all six rotations of the specified piece at the specified index.
361
 * We calculate only half of piece 3's rotations.  This is because any solution
362
 * found has an identical solution rotated 180 degrees.  Thus we can reduce the
363
 * number of attempted pieces in the solve algorithm by not including the 180-
364
 * degree-rotated pieces of ONE of the pieces.  I chose piece 3 because it gave
365
 * me the best time ;)
366
 */
367
 void calc_six_rotations(char piece, char index) {
368
   char rotation, cell[5];
369
   char minimum, first_empty;
370
   unsigned long long piece_mask;
371
 
372
   for(rotation = 0; rotation < 6; rotation++) {
373
      if(piece != 3 || rotation < 3) {
374
         calc_cell_indices(cell, piece, index);
375
         if(cells_fit_on_board(cell, piece) && !has_island(cell, piece)) {
376
            minimum = minimum_of_cells(cell);
377
            first_empty = first_empty_cell(cell, minimum);
378
            piece_mask = bitmask_from_cells(cell);
379
            record_piece(piece, minimum, first_empty, piece_mask);
380
         }
381
      }
382
      rotate_piece(piece);
383
   }
384
}
385
 
386
/* Calculate every legal rotation for each piece at each board location. */
387
void calc_pieces(void) {
388
   char piece, index;
389
 
390
   for(piece = 0; piece < 10; piece++) {
391
      for(index = 0; index < 50; index++) {
392
         calc_six_rotations(piece, index);
393
         flip_piece(piece);
394
         calc_six_rotations(piece, index);
395
      }
396
   }
397
}
398
 
399
 
400
 
401
/* Calculate all 32 possible states for a 5-bit row and all rows that will
402
 * create islands that follow any of the 32 possible rows.  These pre-
403
 * calculated 5-bit rows will be used to find islands in a partially solved
404
 * board in the solve function.
405
 */
406
#define ROW_MASK 0x1F
407
#define TRIPLE_MASK 0x7FFF
408
char all_rows[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
409
      17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
410
int bad_even_rows[32][32];
411
int bad_odd_rows[32][32];
412
int bad_even_triple[32768];
413
int bad_odd_triple[32768];
414
 
415
int rows_bad(char row1, char row2, int even) {
416
   /* even is referring to row1 */
417
   int i, in_zeroes, group_okay;
418
   char block, row2_shift;
419
   /* Test for blockages at same index and shifted index */
420
   if(even)
421
      row2_shift = ((row2 << 1) & ROW_MASK) | 0x01;
422
   else
423
      row2_shift = (row2 >> 1) | 0x10;
424
   block = ((row1 ^ row2) & row2) & ((row1 ^ row2_shift) & row2_shift);
425
   /* Test for groups of 0's */
426
   in_zeroes = FALSE;
427
   group_okay = FALSE;
428
   for(i = 0; i < 5; i++) {
429
      if(row1 & (1 << i)) {
430
         if(in_zeroes) {
431
            if(!group_okay)
432
               return TRUE;
433
            in_zeroes = FALSE;
434
            group_okay = FALSE;
435
         }
436
      } else {
437
         if(!in_zeroes)
438
            in_zeroes = TRUE;
439
         if(!(block & (1 << i)))
440
            group_okay = TRUE;
441
      }
442
   }
443
   if(in_zeroes)
444
      return !group_okay;
445
   else
446
      return FALSE;
447
}
448
 
449
/* Check for cases where three rows checked sequentially cause a false
450
 * positive.  One scenario is when 5 cells may be surrounded where piece 5
451
 * or 7 can fit.  The other scenario is when piece 2 creates a hook shape.
452
 */
453
int triple_is_okay(char row1, char row2, char row3, int even) {
454
   if(even) {
455
      /* There are four cases:
456
       * row1: 00011  00001  11001  10101
457
       * row2: 01011  00101  10001  10001
458
       * row3: 011??  00110  ?????  ?????
459
       */
460
      return ((row1 == 0x03) && (row2 == 0x0B) && ((row3 & 0x1C) == 0x0C)) ||
461
            ((row1 == 0x01) && (row2 == 0x05) && (row3 == 0x06)) ||
462
            ((row1 == 0x19) && (row2 == 0x11)) ||
463
            ((row1 == 0x15) && (row2 == 0x11));
464
   } else {
465
      /* There are two cases:
466
       * row1: 10011  10101
467
       * row2: 10001  10001
468
       * row3: ?????  ?????
469
       */
470
      return ((row1 == 0x13) && (row2 == 0x11)) ||
471
            ((row1 == 0x15) && (row2 == 0x11));
472
   }
473
}
474
 
475
 
476
void calc_rows(void) {
477
   int row1, row2, row3;
478
   int result1, result2;
479
   for(row1 = 0; row1 < 32; row1++) {
480
      for(row2 = 0; row2 < 32; row2++) {
481
         bad_even_rows[row1][row2] = rows_bad(row1, row2, TRUE);
482
         bad_odd_rows[row1][row2] = rows_bad(row1, row2, FALSE);
483
      }
484
   }
485
   for(row1 = 0; row1 < 32; row1++) {
486
      for(row2 = 0; row2 < 32; row2++) {
487
         for(row3 = 0; row3 < 32; row3++) {
488
            result1 = bad_even_rows[row1][row2];
489
            result2 = bad_odd_rows[row2][row3];
490
            if(result1 == FALSE && result2 == TRUE
491
                  && triple_is_okay(row1, row2, row3, TRUE))
492
               bad_even_triple[row1+(row2*32)+(row3*1024)] = FALSE;
493
            else
494
               bad_even_triple[row1+(row2*32)+(row3*1024)] = result1 || result2;
495
 
496
            result1 = bad_odd_rows[row1][row2];
497
            result2 = bad_even_rows[row2][row3];
498
            if(result1 == FALSE && result2 == TRUE
499
                  && triple_is_okay(row1, row2, row3, FALSE))
500
               bad_odd_triple[row1+(row2*32)+(row3*1024)] = FALSE;
501
            else
502
               bad_odd_triple[row1+(row2*32)+(row3*1024)] = result1 || result2;
503
         }
504
      }
505
   }
506
}
507
 
508
 
509
 
510
/* Calculate islands while solving the board.
511
 */
512
int boardHasIslands(char cell) {
513
   /* Too low on board, don't bother checking */
514
   if(cell >= 40)
515
      return FALSE;
516
   int current_triple = (board >> ((cell / 5) * 5)) & TRIPLE_MASK;
517
   if((cell / 5) % 2)
518
      return bad_odd_triple[current_triple];
519
   else
520
      return bad_even_triple[current_triple];
521
}
522
 
523
 
524
/* The recursive solve algorithm.  Try to place each permutation in the upper-
525
 * leftmost empty cell.  Mark off available pieces as it goes along.
526
 * Because the board is a bit mask, the piece number and bit mask must be saved
527
 * at each successful piece placement.  This data is used to create a 50 char
528
 * array if a solution is found.
529
 */
530
short avail = 0x03FF;
531
char sol_nums[10];
532
unsigned long long sol_masks[10];
533
signed char solutions[2100][50];
534
int solution_count = 0;
535
int max_solutions = 2100;
536
 
537
void record_solution(void) {
538
   int sol_no, index;
539
   unsigned long long sol_mask;
540
   for(sol_no = 0; sol_no < 10; sol_no++) {
541
      sol_mask = sol_masks[sol_no];
542
      for(index = 0; index < 50; index++) {
543
         if(sol_mask & 1ULL) {
544
            solutions[solution_count][index] = sol_nums[sol_no];
545
            /* Board rotated 180 degrees is a solution too! */
546
            solutions[solution_count+1][49-index] = sol_nums[sol_no];
547
         }
548
         sol_mask = sol_mask >> 1;
549
      }
550
   }
551
   solution_count += 2;
552
}
553
 
554
void solve(int depth, int cell) {
555
   int piece, rotation, max_rots;
556
   unsigned long long *piece_mask;
557
   short piece_no_mask;
558
 
559
   if(solution_count >= max_solutions)
560
      return;
561
 
562
   while(board & (1ULL << cell))
563
      cell++;
564
 
565
   for(piece = 0; piece < 10; piece++) {
566
      piece_no_mask = 1 << piece;
567
      if(!(avail & piece_no_mask))
568
         continue;
569
      avail ^= piece_no_mask;
570
      max_rots = piece_counts[piece][cell];
571
      piece_mask = pieces[piece][cell];
572
      for(rotation = 0; rotation < max_rots; rotation++) {
573
         if(!(board & *(piece_mask + rotation))) {
574
            sol_nums[depth] = piece;
575
            sol_masks[depth] = *(piece_mask + rotation);
576
            if(depth == 9) {
577
               /* Solution found!!!!!11!!ONE! */
578
               record_solution();
579
               avail ^= piece_no_mask;
580
               return;
581
            }
582
            board |= *(piece_mask + rotation);
583
            if(!boardHasIslands(next_cell[piece][cell][rotation]))
584
               solve(depth + 1, next_cell[piece][cell][rotation]);
585
            board ^= *(piece_mask + rotation);
586
         }
587
      }
588
      avail ^= piece_no_mask;
589
   }
590
}
591
 
592
 
593
/* qsort comparator - used to find first and last solutions */
594
int solution_sort(const void *elem1, const void *elem2) {
595
   signed char *char1 = (signed char *) elem1;
596
   signed char *char2 = (signed char *) elem2;
597
   int i = 0;
598
   while(i < 50 && char1[i] == char2[i])
599
      i++;
600
   return char1[i] - char2[i];
601
}
602
 
603
 
604
/* pretty print a board in the specified hexagonal format */
605
void pretty(signed char *b) {
606
   int i;
607
   for(i = 0; i < 50; i += 10) {
608
      printf("%c %c %c %c %c \n %c %c %c %c %c \n", b[i]+'0', b[i+1]+'0',
609
            b[i+2]+'0', b[i+3]+'0', b[i+4]+'0', b[i+5]+'0', b[i+6]+'0',
610
            b[i+7]+'0', b[i+8]+'0', b[i+9]+'0');
611
   }
612
   printf("\n");
613
}
614
 
615
int main(int argc, char **argv) {
616
   if(argc > 1)
617
      max_solutions = atoi(argv[1]);
618
   calc_pieces();
619
   calc_rows();
620
   solve(0, 0);
621
   printf("%d solutions found\n\n", solution_count);
622
   qsort(solutions, solution_count, 50 * sizeof(signed char), solution_sort);
623
   pretty(solutions[0]);
624
   pretty(solutions[solution_count-1]);
625
   return 0;
626
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.