How to get loop bounds in LLVM? - loops

I want to get the loop bounds by using LLVM API. Here is the part of the code as follows. I don't know whether it is right to get the bounds. So, is there any other situation that I haven't thought about?
typedef std::vector<Loop*> LoopNest;
typedef std::vector<const Value*> LoopNestBounds;
...
void getLoopNestBounds(const LoopNest &Nest, LoopNestBounds &LBounds) {
ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
for (unsigned d = 0, n = Nestsize(); d != n; ++d) {
if (SE.hasLoopInvariantBackedgeTakenCount(Nest[d])) {
const SCEV *C = SE.getBackedgeTakenCount(Nest[d]);
const SCEVConstant *CC = dyn_cast<const SCEVConstant>(C);
LBounds.push_back(CC->getValue());
errs() << CC->getValue()->getValue() << " iterations\n";
}
else {
LBounds.push_back(0);
errs() << "---- 0 iterations for the nest ----" << "\n";
}
}
}
Note: the version of LLVM is 3.0.

Related

Find Nth number from a sorted array formed by multiplying any two or more consecutive natural numbers

I recently encountered this problem:
There is a (increasingly) sorted array formed by multiplying any two or more consecutive natural numbers.
2, 6, 12, 20, 24, 30, 42, 56, 60, 72 ...
Ex. 2 is formed by two consecutive natural numbers 1 and 2: 2 = 1×2. And 6 = 2×3 OR 1×2×3, 20 = 4×5.
If n is given as a parameter, find the nth number from the above array and return.
Limitation
1 ≤ n ≤ 1000000
n is given only when the answer is smaller than 1012
So here I was able to find O(n2) solution, but I want to know if there is a better solution.
My O(n2) JS solution:
function solution(n) {
// Find all possible product subsets of [1, ..., n] = [1x2, 2x3, 4x5, ..., 1x2x...xn]
// return Nth index of this product subset array
// 1 ~ n+1 array
const nums = Array.from({ length: n+1 }, (_, i) => i + 1);
const set = new Set();
// Find all possible product subsets
for (let i = 0; i < nums.length; i++) {
let accu = 1;
for (let j = i; j < nums.length; j++) {
accu *= nums[j];
if (i !== j) set.add(accu);
}
}
// Sort and return n-1 index value
return Array.from(set).sort((a,b) => a - b)[n-1];
}
Thanks for the help :)
The following implementation is based on a min-heap (std::priority_queue in C++), that memorizes the "best" future candidates.
One important point is to treat the basic solutions k *(k+1) differently. As it is likely that these numbers are in the majority, this allows to greatly reduce the size of the heap.
At each given time, we either decide to use a k(k+1)number, or to use the current top value of the min-heap.
Each used value led to insertion of a new candidate in the min-heap.
Another aspect is to only insert in the heap the values less then the estimated max value, n(n+1).
The complexity is estimated to be O(n log M), where M is the mean size of the heap.
For n = 10^6, the programme measures that the maximum size of the heap is equal to 9998, much less than n.
On my PC, I get the result for n = 10^6 in 11 ms. Result: 977410038240
Here is the C++ code.
This code memorizes all the sequence, mainly for debugging. In practice, if we only need the nth value, such memorization can be avoided. The measurement of the maximum heap (useful for debugging) size can be removed too, if efficiency is still a concern.
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <chrono>
template <typename T>
void print (const std::vector<T> &A , const std::string &s = "") {
std::cout << s;
for (const T& val: A) {
std::cout << val << " ";
}
std::cout << "\n";
}
struct Prod {
long long p; // product
int last; // last integer in the product
};
long long int consecutive_products (int n) {
std::vector<long long> products; // not strictly needed, for debugging
products.reserve(n);
products.push_back (2); products.push_back (6);
long long max_val = (long long) n * (n+1);
auto comp = [] (const Prod& x1, const Prod& x2) {
if (x1.p == x2.p) return x1.last > x2.last;
return x1.p > x2.p;
};
std::priority_queue<Prod, std::vector<Prod>, decltype(comp)> candidates(comp);
if (n <= 2) return products[n-1];
candidates.push ({24, 4}); // 2*3*4 -> extension of 2*3
long long int prod_simple = 12; // = 3*4 - simple products k(k-1) are dealt with differently
int rank_simple = 4;
int index = 2;
long long current_val = products[index - 1];
Prod best;
long long minval;
int max_size = 0;
while (index < n) {
if (candidates.empty()) {
minval = max_val;
} else {
best = candidates.top();
minval = best.p;
}
if (minval <= prod_simple) {
candidates.pop();
long long new_product = minval * (best.last + 1);
if (new_product < max_val) {
candidates.push ({new_product, best.last + 1});
}
} else {
minval = prod_simple;
long long new_product = prod_simple * (rank_simple + 1);
if (new_product < max_val) {
candidates.push ({new_product, rank_simple + 1});
}
prod_simple = (long long) rank_simple * (rank_simple + 1);
rank_simple++;
}
if (minval > current_val) {
products.push_back(minval);
current_val = minval;
index++;
}
int size = candidates.size();
if (size > max_size) max_size = size;
}
if (n <= 20) print (products, "Products: ");
std::cout << "max heap size = " << max_size << std::endl;
return minval;
}
int main() {
int n;
std::cout << "Enter n: ";
std::cin >> n;
auto t1 = std::chrono::high_resolution_clock::now();
auto ans = consecutive_products (n);
auto t2 = std::chrono::high_resolution_clock::now();
std::cout << ans << std::endl;
auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
std::cout << "duration = " << duration << " micro-s" << std::endl;
return 0;
}

Problem implementing alpha-beta pruning for chess engine

I have been working on a chess engine recently, and I am ready to implement some kind of AI to actually play the game (search positions). I have written an alpha-beta pruning algorithm, but it doesn't return the best moves when i test it.
The code for the alpha-beta search is:
float Search::alphabeta(S_BOARD* pos, S_SEARCHINFO *info, int depth, float alpha, float beta){
if (depth == 0) {
info->nodes++;
return eval::staticEval(pos);
}
info->nodes++;
S_MOVELIST list;
MoveGeneration::validMoves(pos, list);
float value = 0;
S_MOVE bestMove;
bestMove.move = NOMOVE;
bestMove.score = 0;
float prevBound = (pos->whitesMove == WHITE) ? alpha : beta;
int pvMove = TT::probeMove(pos);
if (pvMove != NOMOVE) {
for (int i = 0; i < list.count; i++) {
if (list.moves[i].move == pvMove) {
list.moves[i].score = 20000000;
break;
}
}
}
if (pos->whitesMove == WHITE) {
value = -INFINITE;
for (int moveNum = 0; moveNum < list.count; moveNum++) {
pickNextMove(moveNum, &list);
MoveGeneration::makeMove(*pos, list.moves[moveNum].move);
value = max(value, alphabeta(pos, info, depth - 1, alpha, beta));
MoveGeneration::undoMove(*pos);
if (value > alpha) {
if (value >= beta) {
if (moveNum == 0) {
info->fhf++;
}
info->fh++;
break;
}
alpha = value;
bestMove = list.moves[moveNum];
}
}
if (pos->is_checkmate) {
return -MATE + pos->ply;
}
else if (pos->is_stalemate) {
return 0;
}
if (alpha != prevBound) {
TT::storePvMove(pos, bestMove);
}
return value;
}
else {
value = INFINITE;
for (int moveNum = 0; moveNum < list.count; moveNum++) {
pickNextMove(moveNum, &list);
MoveGeneration::makeMove(*pos, list.moves[moveNum].move);
value = min(value, alphabeta(pos, info, depth - 1, alpha, beta));
MoveGeneration::undoMove(*pos);
if (value < beta){
if (beta <= alpha) {
if (moveNum == 0) {
info->fhf++;
}
info->fh++;
break;
}
beta = value;
bestMove = list.moves[moveNum];
}
}
if (pos->is_checkmate) {
return MATE - pos->ply;
}
else if (pos->is_stalemate) {
return 0;
}
if (beta != prevBound) {
TT::storePvMove(pos, bestMove);
}
return value;
}
(MoveGeneration is a namespace, so it isn't a problem with calling functions outside of object instances.)
I run the function inside an iterative deepening function, which is as follows:
float Search::searchPosition(S_BOARD* pos, S_SEARCHINFO *info){
clearForSearch(pos, info);
float score = -INFINITE;
int bestMove = NOMOVE;
int pvMoves = 0;
// Iterative deepening.
for (int currDepth = 1; currDepth <= info->depth; currDepth++){
auto start = std::chrono::high_resolution_clock::now();
score = alphabeta(pos, info, currDepth, -INFINITE, INFINITE);
auto end = std::chrono::high_resolution_clock::now();
pvMoves = TT::getPvLine(pos, currDepth);
bestMove = pos->pvArray[0];
std::chrono::duration<double> elapsed = end - start;
std::cout << "[+] Depth: " << currDepth << " score: " << score << " move: " << printMove(bestMove)
<< " nodes: " << info->nodes << " kN/s: " << (info->nodes/elapsed.count())/1000 << std::endl;
std::cout << "pv";
for (int i = 0; i < pvMoves; i++){
std::cout << " " << printMove(pos->pvArray[i]);
}
std::cout << std::endl;
std::cout << "Ordering: " << info->fhf/info->fh << std::endl;
}
return score;}
Can anyone please help me by pointing out potential errors i have made?
Thank you for your help, and just tell me if i need to upload more of my code.
it doesn't return a move since you are only returning the value at the bottom of your alpha/beta function. In the original call, put this:
move, score = alphabeta(pos, info, currDepth, -INFINITE, INFINITE);
In your depth == 0, checkmate and stalemate you return:
return None, eval
At the end of your two player functions (minimizing and maximizing player) you return:
return move, value
Finally, when you make the recursive calls from your two player functions, you need to only obtain the value. I am not sure about your programming language, but in e.g. Python you put a [1] at the end to just get the value and not the move, something like this:
value = max(value, alphabeta(pos, info, depth - 1, alpha, beta))[1]

Is it possible to use a repetition structure in this code?

What I want is to optimize this part of my code. It is just repeating itself but I don't know how to use a repetition structure here using the defines I used.
I defined the GPIO_Ports and Pins.
And this go forward until SEL8.
if (out & (1 << 0)) {
GPIO_SetBits(SEL0_GPIO_Port, SEL0_Pin);
} else {
GPIO_ResetBits(SEL0_GPIO_Port, SEL0_Pin);
}
if (out & (1 << 1)) {
GPIO_SetBits(SEL1_GPIO_Port, SEL1_Pin);
} else {
GPIO_ResetBits(SEL1_GPIO_Port, SEL1_Pin);
}
if (out & (1 << 2)) {
GPIO_SetBits(SEL2_GPIO_Port, SEL2_Pin);
} else {
GPIO_ResetBits(SEL2_GPIO_Port, SEL2_Pin);
}
We don't know the types of variables used. The code could look something like this:
#include <assert.h>
// Indexas valid are from 0 to 8, some 9
#define IDX_MAX 9
typedef /* insert the type of SELx_GPIO_Port here */ gpio_port_type;
static gpio_port_type get_gpio_port_from_idx(size_t idx) {
const gpio_port_type ports[] = {
SEL0_GPIO_Port,
SEL1_GPIO_Port,
SEL2_GPIO_Port,
SEL3_GPIO_Port,
SEL4_GPIO_Port,
SEL5_GPIO_Port,
SEL6_GPIO_Port,
SEL7_GPIO_Port,
SEL8_GPIO_Port,
};
static_assert(IDX_MAX == sizeof(ports)/sizeof(*ports));
assert(idx < sizeof(ports)/sizeof(*ports));
return ports[idx];
}
typedef /* insert the type of SELx_Pin here */ pin_type ;
static pin_type get_sel_pin_from_idx(size_t idx) {
const pin_type pins[] = {
SEL0_Pin,
SEL1_Pin,
SEL2_Pin,
SEL3_Pin,
SEL4_Pin,
SEL5_Pin,
SEL6_Pin,
SEL7_Pin,
SEL8_Pin,
};
static_assert(IDX_MAX == sizeof(pins)/sizeof(*pins));
assert(idx < sizeof(pins)/sizeof(*pins));
return pins[idx];
}
void set_out(int out) {
for (size_t i = 0; i < IDX_MAX; ++i) {
(
(out & (1 << i)) ? GPIO_SetBits : GPIO_ResetBits
)(get_gpio_port_from_idx(i), get_gpio_pin_from_idx(i));
}
}
The first two functions map a static index from the range of 0 to 8 to SELx_GPIO_Port and SELx_Pin variables respectively. After that the set_out function checks each bit in the input variable int out and calls the GPIO_SetBits or GPIO_ResetBits depending if the bit is set or unset. I used ternary operator, if the function would have different prototype, or are macros, you could just:
void set_out(int out) {
for (size_t i = 0; i < IDX_MAX; ++i) {
if (out & (1 << i)) {
GPIO_SetBits(get_gpio_port_from_idx(i), get_gpio_pin_from_idx(i));
} else {
GPIO_ResetBits(get_gpio_port_from_idx(i), get_gpio_pin_from_idx(i));
}
}
}

Function calculate results wrong answer

I'm doing an exercise and I stuck with my code. I hope you guys can help me fix it.
And here is my function fen():
double fen(double x,double y, int n) { // You should complete this function
// Write your statements here
double sum=1,temp;
int j=2,k=1;
double a = (x*y*y) / 18;
sum=1-a;
for(int i=2;i<=n;i++)
{
for(;j<=i;j++)
{
a *= (x*y);
for(;k<=(i+j);k++)
a /= k;
}
temp = a/(k*k);
temp = (i%2 == 0) ? temp : -temp;
sum+=temp;
}
return sum; //This statement must be changed
}
I've checked many times but still don't know why its result's wrong.
I've debugged and when i=3, a actually equal to 0.025 but it displayed0.02499999999.
I wrote a small code to simplify things and here it is:
#include <iostream>
using namespace std;
double fen(double x,double y, int n) {
double tmp = y;
double sum = 1;
for (int i = 1; i < n; i++) {
tmp *= -((x * y * (2*i-1)) / ((2*i) * (2*i+1) * (2*i+1)));
sum += tmp;
}
return sum;
}
int main(void) {
cout << fen(2,3,1) << endl;
cout << fen(2,3,2) << endl;
cout << fen(2,3,3) << endl;
cout << fen(2,3,4) << endl;
cout << fen(2,3,1000) << endl;
return 0;
}
I only checked it till fen(2,3,4) and results were correct till there. it shows 0.162772 for fen(2,3,1000):
1
0
0.18
0.161633
0.162772
UPDATE:
Updated code to use cout for output rather than printf. But I don't think this code really differs between C or C++.
In addition, remember that you reach quickly to limit of numerical precision of double in this code.
OP's formula mis-calculates the terms.
// int j=2,k=1;
int j=2,k=3; // The loop's later calculation expect this to be initially 3
// in the loop
// add
a *= k; // undo the prior terms /k
for(;j<=i;j++) {
// this part OK
}
// temp = a/(k*k);
temp = a/k*; // Only need /k
Other simplifications possible.

Could not able to understand Obfuscated C Code [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I saw this code in http://www.cise.ufl.edu/~manuel/obfuscate/obfuscate.html (http://www.cise.ufl.edu/~manuel/obfuscate/savastio) website.But this code is very very crazy. I could not able to understand what is happening when it is happening.
Please help me. Let me know what is happening when each line is getting executed.
e.g. printf function is there, if we will see there is no statement called as "Enter the number". But still while executing it is asking "Enter the number". From where it is comming.
And why the code is written like this. It looks like "n!"(Though it means factorial).
Please help me.
#include <stdio.h>
#define l11l 0xFFFF
#define ll1 for
#define ll111 if
#define l1l1 unsigned
#define l111 struct
#define lll11 short
#define ll11l long
#define ll1ll putchar
#define l1l1l(l) l=malloc(sizeof(l111 llll1));l->lll1l=1-1;l->ll1l1=1-1;
#define l1ll1 *lllll++=l1ll%10000;l1ll/=10000;
#define l1lll ll111(!l1->lll1l){l1l1l(l1->lll1l);l1->lll1l->ll1l1=l1;}\
lllll=(l1=l1->lll1l)->lll;ll=1-1;
#define llll 1000
l111 llll1 {
l111 llll1 *
lll1l,*ll1l1 ;l1l1 lll11 lll [
llll];};main (){l111 llll1 *ll11,*l1l,*
l1, *ll1l, * malloc ( ) ; l1l1 ll11l l1ll ;
ll11l l11,ll ,l;l1l1 lll11 *lll1,* lllll; ll1(l
=1-1 ;l< 14; ll1ll("\t\"8)>l\"9!.)>vl" [l]^'L'),++l
);scanf("%d",&l);l1l1l(l1l) l1l1l(ll11 ) (l1=l1l)->
lll[l1l->lll[1-1] =1]=l11l;ll1(l11 =1+1;l11<=l;
++l11){l1=ll11; lll1 = (ll1l=( ll11=l1l))->
lll; lllll =( l1l=l1)->lll; ll=(l1ll=1-1
);ll1(;ll1l-> lll1l||l11l!= *lll1;){l1ll
+=l11**lll1++ ;l1ll1 ll111 (++ll>llll){
l1lll lll1=( ll1l =ll1l-> lll1l)->lll;
}}ll1(;l1ll; ){l1ll1 ll111 (++ll>=llll)
{ l1lll} } * lllll=l11l;}
ll1(l=(ll=1- 1);(l<llll)&&
(l1->lll[ l] !=l11l);++l); ll1 (;l1;l1=
l1->ll1l1,l= llll){ll1(--l ;l>=1-1;--l,
++ll)printf( (ll)?((ll%19) ?"%04d":(ll=
19,"\n%04d") ):"%4d",l1-> lll[l] ) ; }
ll1ll(10); }
As a start, you can get the code indented properly and remove the indirection caused by the #defines. The indentation can be done by GNU indent and gcc -E will do the preprocessing. Assuming the code is in factorial.c (this requires using the command line):
> gcc -E factorial.c | indent > clean_factorial.c
A thing to note is the preprocessing step will dump all of stdio.h into clean_factorial.c; but that is irrelevant information, so we should comment out/delete #include<stdio.h> before running gcc -E. This basically gives:
struct llll1
{
struct llll1 *lll1l, *ll1l1;
unsigned short lll[1000];
};
main ()
{
struct llll1 *ll11, *l1l, *l1, *ll1l, *malloc ();
unsigned long l1ll;
long l11, ll, l;
unsigned short *lll1, *lllll;
for (l = 1 - 1; l < 14; putchar ("\t\"8)>l\"9!.)>vl"[l] ^ 'L'), ++l);
scanf ("%d", &l);
l1l = malloc (sizeof (struct llll1));
l1l->lll1l = 1 - 1;
l1l->ll1l1 = 1 - 1;
ll11 = malloc (sizeof (struct llll1));
ll11->lll1l = 1 - 1;
ll11->ll1l1 = 1 - 1;
(l1 = l1l)->lll[l1l->lll[1 - 1] = 1] = 0xFFFF;
for (l11 = 1 + 1; l11 <= l; ++l11)
{
l1 = ll11;
lll1 = (ll1l = (ll11 = l1l))->lll;
lllll = (l1l = l1)->lll;
ll = (l1ll = 1 - 1);
for (; ll1l->lll1l || 0xFFFF != *lll1;)
{
l1ll += l11 ** lll1++;
*lllll++ = l1ll % 10000;
l1ll /= 10000;
if (++ll > 1000)
{
if (!l1->lll1l)
{
l1->lll1l = malloc (sizeof (struct llll1));
l1->lll1l->lll1l = 1 - 1;
l1->lll1l->ll1l1 = 1 - 1;;
l1->lll1l->ll1l1 = l1;
}
lllll = (l1 = l1->lll1l)->lll;
ll = 1 - 1;
lll1 = (ll1l = ll1l->lll1l)->lll;
}
}
for (; l1ll;)
{
*lllll++ = l1ll % 10000;
l1ll /= 10000;
if (++ll >= 1000)
{
if (!l1->lll1l)
{
l1->lll1l = malloc (sizeof (struct llll1));
l1->lll1l->lll1l = 1 - 1;
l1->lll1l->ll1l1 = 1 - 1;;
l1->lll1l->ll1l1 = l1;
}
lllll = (l1 = l1->lll1l)->lll;
ll = 1 - 1;
}
}
*lllll = 0xFFFF;
}
for (l = (ll = 1 - 1); (l < 1000) && (l1->lll[l] != 0xFFFF); ++l);
for (; l1; l1 = l1->ll1l1, l = 1000)
{
for (--l; l >= 1 - 1; --l, ++ll)
printf ((ll) ? ((ll % 19) ? "%04d" : (ll =
19, "\n%04d")) : "%4d",
l1->lll[l]);
}
putchar (10);
}
This is slightly readable, and we can do things like rename variables so that we can tell them apart easily, even if we don't know what they do yet. E.g. this will rename the struct to structure, and call the pointers inside it left and right (you can do this with the find-replace tool in your editor too):
> sed -i 's/llll1/structure/g; s/lll1l/left/g; s/ll1l1/right/g;' clean_factorial.c
(you have to be careful of the order, or the replacement for lll might conflict with lllll, for example).
There are some other easy things to do:
1 - 1 occurs a lot: replace it with 0 (and 1 + 1 too, except replace that with 2 instead of 0).
The line with "\t\"8)>l\"9!.)>vl"[l] ^ 'L' just goes along the string printing each character after xor'ing it with 'L' (work out why! It might help to put the putchar in the body of the for loop, rather than in the comma-statement).
putchar(10) just prints a new line.
Know about the comma operator.
Other than that, it's just a lot of hard work. You can and should use tools like a debugger to trace the flow of execution and work out what is happening where.
Here's my attempt at unwrapping it, got a bit stuck on the prompt logic, so I just initialized longC to zero, and printed out the request for a number manually:
#include <stdio.h>
struct StructName
{
struct StructName *structA, *structB;
unsigned short unsignedShortArrayA[1000];
};
main ()
{
struct StructName *structC, *structD, *structE, *structF, *malloc();
unsigned long unsignedLongA;
long longA, longB, longC = 0;
unsigned short *unsignedShortA, *unsignedShortB;
//for(longC=0; longC< 14; putchar("\t\"8)>longC\"9!.)>vl" [longC]^'longC'),++longC )
//;
printf("%s", "Enter a number: " );
scanf("%d", &longC);
structD = malloc(sizeof(struct StructName));
structD->structA=0;
structD->structB=0;
structC=malloc(sizeof(struct StructName));
structC->structA=0;
structC->structB=0;
(structE=structD)->unsignedShortArrayA[structD->unsignedShortArrayA[0] =1] = 0xFFFF;
for( longA=1+1;longA<=longC;++longA)
{
structE=structC;
unsignedShortA = (structF=( structC=structD))->unsignedShortArrayA;
unsignedShortB =( structD=structE)->unsignedShortArrayA;
longB=(unsignedLongA=0);
for( ; structF->structA || 0xFFFF != *unsignedShortA; )
{
unsignedLongA+=longA**unsignedShortA++;
*unsignedShortB++=unsignedLongA%10000;
unsignedLongA/=10000;
if( ++longB>1000 )
{
if( !structE->structA )
{
structE->structA=malloc(sizeof(struct StructName));
structE->structA->structA=0;
structE->structA->structB=0;
structE->structA->structB=structE;
}
unsignedShortB=(structE=structE->structA)->unsignedShortArrayA;
longB=0;
unsignedShortA=( structF =structF-> structA)->unsignedShortArrayA;
}
}
for( ; unsignedLongA; )
{
*unsignedShortB++=unsignedLongA%10000;
unsignedLongA/=10000;
if( ++longB>=1000 )
{
if( !structE->structA )
{
structE->structA=malloc(sizeof(struct StructName));
structE->structA->structA=0;
structE->structA->structB=0;
structE->structA->structB=structE;
}
unsignedShortB=(structE=structE->structA)->unsignedShortArrayA;
longB=0;
}
}
* unsignedShortB=0xFFFF;
}
for( longC=(longB=1- 1); (longC<1000) && (structE->unsignedShortArrayA[ longC] !=0xFFFF); ++longC )
{
;
}
for( ; structE; structE=structE->structB, longC=1000 )
{
for( --longC; longC>=0; --longC, ++longB)
{
printf( (longB)?((longB%19) ? "%04d" : (longB=19,"\n%04d") ):"%4d",structE-> unsignedShortArrayA[longC] );
}
}
putchar(10);
}
EDIT: Cleaned up a bit.

Resources