[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]
 

It's very famous issue. That's why using floating point operation is difficult.
Especially, round-off can make up to 0.5f erratum.
In calculation for drawing on pixels, round-off is frequently used - Do not consider blending and anti-aliasing. And even sum of two errata can make 1 pixel erratum. So, we should always keep this in mind when implement pixel-relative-calculation.

Here is example.

Line L passes point P0 and P1.
Drawing two lines those are orthogonal to L, L-symmetric, passes point P2, P3 respectively and length is R.

As you know, there two lines should be parallel.
But, in this case, we should calculate two end points - the results may be float type. To draw this we should make those as an integer value (usually by using round-off).
For each line, up to 0.5f erratum can exist. So, for two lines, up to 1 pixel erratum can be raised. So, when these two lines are drawn on the canvas, they may not be parallel.

'Domain > Software' 카테고리의 다른 글

[GNU] Issues of cross-compiling in GNU build system.  (0) 2011.04.21
[Tips] Cyclic Queue  (0) 2010.10.18
[SW] Questions to evaluate SW Engineer  (0) 2009.04.09
[Prog] Using so-called 'context' data structure.  (0) 2008.01.10
[Spec] DWARF2  (0) 2006.08.30
[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

'shift' operator in C extends sign bit.

int a = 0xffffffff;
a = a>>8; // a == 0xffffffff

Due to sign of 'a' is minus, '>>8' preserve it's sign.
But, 'unsigned' value is always '>=0' So, sign bit doesn't need to be extended. So, front parts is filled with '0'.

unsigned int a = 0xffffffff
a = a >>8; // a == 0x00ffffff

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

Stack can be classified into "Full Stack" and "Empty Stack" by addressing mode.

Full Stack : The stack pointer points to the last item in the stack.
Empty Stack : The stack pointer points to the next free space on the stack.

I prefer Empty Stack because... how can I say... It is more computer-like-expression.... :-)
Usually, in computer science, indexing starts like (i=start) and ends like (i<end)... That is, [a, b) range concept is normal...
In Empty Stack, we can say "Stack is empty" by checking (SP == Framebase). And this is more suitable for above concept...

'Study > Computer Science' 카테고리의 다른 글

[Study] Understanding XOR operation  (0) 2008.07.07
[Study] Ascending Stack Vs. Descending Stack  (0) 2007.02.07

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

Ideally, duplicated code leads to maintenance nightmare. So, Not-allowing-duplicated-code always seems to be better. But, in this article, I want to say that in some cases, code-duplication needs to be allowed.

In practice, lots of people who has different ability work together in one source code branch. In this case, if code duplication is not allowed, all developer should search all sources to find the reusable module. Let's image that there are thousands modules. Finding appropriate module is not easy. And lots of people try to customize(modify) the module for easy-reuse. If all engineers are enough good at programming and enough time to consider code quality then we don't need to worry about "customization". But, it cannot be in some cases - especially, product development. Skill level of engineers are always various and they are always pushed by project schedule. So, the shared module tends to become worse and worse in terms of its quality. (It's normal in large-size-project).

Here is merits of allowing code duplication.(There are lots of well-known-disadvantage of allowing code duplication. So, let's talk about only "Merits".)
  * There is no dependency among people. So, it's very easy to work in parallel.
  * Merging is easy, because of no-dependency and no-conflicts.
  * Bug from mistake affects only limited area. So, detecting issued part is easy.

So, practically, we need to consider what should be reused(shared) and what shouldn't.

Here is my opinion about this.
Codes that should not be duplicated.
  - codes for interface with external modules.(In App. point of view, OS, filesystem and so on can be external modules)
  - codes that are used very frequently. (ex. code for getting lengh of string. - strlen)
  - stable codes.
  - ... (anything else???)

Codes that can be duplicated.
  - parts that should be done in parallel with tight schedule and enough human resources.
  - codes that are customized very often.
  - ... (anything else???)

Hmm... I need further study...

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

This is tip to define 'enum' that has quite lots of items and important information - ex thread id, event id, etc...

(*1)

// File : "main"

enum
{
    enum01,
    enum02,
    ...
}
...

This is not recommended.
How about using following way?

(*2)

// File : "enum.h "

DEF_ENUM(enum01)
DEF_ENUM(enum02)
...

------------------

// File : "main

#define DEF_ENUM(x)   x,
enum
{
    #include "enum.h"
}
#undef DEF_ENUM

Why this way is better? Let's assume that you want to print 'enum' values.
In (*1) case, only number value can be printed. But in (*2) case, even enum name - string - can be easily printed by following way.

// File : "Enum_str.c"

#define DEF_ENUM(x)   #x,
static const char* enum_str[] =
{
    #include "enum.h"
};
...

printf("%s", enum_str[enum_id]);

It is good, isn't it?
Except for this, you can find other lots of useful ways by using macro.

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

====================================================

// From MSDN

#define paster( n ) printf( "token" #n " = %d", token##n )
int token9 = 9;

If a macro is called with a numeric argument like

paster( 9 );

the macro yields

printf( "token" "9" " = %d", token9 );

which becomes

printf( "token9 = %d", token9 );

====================================================

',' is used as parameter separator in C/C++. So, function which uses variable number of parameter - like "logger(const char* format, ...)" - is difficult to present by using macro. (Some compilers support variable number of parameter in macro too. But, most are not.)
In this case, we can make those be on parameter by groupping all parameters with "()".
For example,

#ifdef _DEBUG_
#   define LOGGER(X) logger X
#else // _DEBUG_
// we don't need to run log function in release build!
#   define LOGGER(X)
#endif // _DEBUG_
...
LOGGER((”print :%d, %d”, a, b)); // == logger(“print:%d, %d”, a, b);
...

=====================================================

To track a function, following way is very common.

// foo_fnc. h :
#ifdef CODE_DEBUG
#   define REAL_fnc(a, b) real_fnc(a, b, __FILE__, __LINE__)
#else
#   define REAL_fnc(a,b) real_fnc(a,b)
#endif

But, In following cases, some compiler raises error.

#ifdef 1
REAL_fnc(a,
#else
NEW_REAL_fnc(a,
#endif
    b);

Yes. It's a kind of porting issue.
In this case, we can use following walk-around.

// foo_fnc. h :
#ifdef CODE_DEBUG
    typedef int (* RealType_Fnc)(int, int)
#   define REAL_fnc real_fnc_wrap(__FILE__, __LINE__)
    extern RealType_Fnc real_fnc_wrap(char*, int);
#else
#   define REAL_fnc(a,b) real_fnc(a,b)
#endif

---------

// foo_fnc.c
...(omitted)
RealType_Fnc real_fnc_wrap(char* fileName, int line)
{
    printf(“%s : %d”, fileName, line);
    return real_fnc;
}
[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

Usually, loop requires overheads - checking condition, jump. Especially, jump breaks pipeline and it results in performance loss. So, we need unrolling loop.

Before unrolling, we should consider followings.
1. Unrolling increases code size. So, we should consider instruction cache size. That is, we should unroll code without decreasing cache hit rate.
2. What is best unrolling value? Some reports said that '16'(16 operations per one loop) is enough.

And, here is coding example for unrolling.

#define UNROLL8( x, s, cond ) \
do { \
    switch( (s) & 0x7 ) \
    { \
        case 0: do  \
                {  \
                    x; \
        case 7:     x; \
        case 6:     x; \
        case 5:     x; \
        case 4:     x; \
        case 3:     x; \
        case 2:     x; \
        case 1:     x; \
            } while( cond ); \
    } \
} while(0)

Usage : UNROLL8(*dst = *src; dst++; src++;, loop_count, dst < dst_end)
[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

큰 팀이 project를 할 경우, 팀내 개발자 각각의 local환경이 서로 틀려서, 문제가 생길때가 많다. ("나는 build가 잘 되는데, 너는 왜 안되느냐?" 등). 그래서 보통의 경우, 같은 project를 하는 사람들끼리는 개발환경을 통일하는 경우가 많고, 이런 개발환경에 대한 script file또한 형상관리의 대상이 되는 경우가 일반적이다. 환경을 통일하기 위해서는 각 개인의 Local환경을 공통 환경으로 Mapping시켜 주는 일이 필요한데, 보통의 경우, 환경 변수, Virtual Drive 등이 쓰인다.

예를 들면,
- 개발 root directory는 "P:\project"로 한다. => Virtual drive를 이용.
- project build directory는 %MY_PRJ%\%PRODUCT_NAME%으로 한다. 등등

그런데, 개발환경이란, 비단, file path, 개발 tool의 path, 환경 변수의 차이 등을 의미하는 것 만이 아니다. source code editor도 주요한 개발환경이라고 할 수 있다.

어느 한 'A'라는 editor에서 개발한 사람이 줄을 잘 맞추어서 정돈된 코드를 만들었다고 하자, 이 코드가 'B'라는 editor에서는, 'tab size의 차이', 'font의 width'차이 등으로 인하여 무질서 하게 보이는 경우가 허다하다. 즉, 'A'라는 editor를 기준으로한 code beautify는 'B'라는 editor에서는 무의미할 수도 있다는 말이다.
그런데 문제는 다른 개발 환경과는 달리, code editor는 개발자들에게 '통일'을 강조하기 어려운 면이 있다는 것이다. 왜냐하면, 개발자들이 다년간 사용한 editor를 바꾸게 된다면, 한동안 새로운 editor에 익숙해 지기까지 꽤나 긴 시간동안 생산성이 크게 떨어질 뿐만 아니라, 개발자 개개인의 커다란 반발을 살 가능성도 농후하기 때문이다.

따라서 차선책으로, editor 환경을 통일시키게 된다. 개개인 개발할 때는 임의의 editor환경을 사용해도 좋지만, code branch에 'submit'한다던가, 'check in'할 경우는 반드시 통일된 editor환경에서 beautify된 코드를 사용하도록 해야 한다. (사실 매번 submit혹은 check in할때마다 이런 작업을 해야 한다면, 개발자들은 차라리, editor환경을 여기에 맞추게 된다. editor환경을 바꾸는 일은 editor자체를 바꾸는 것보다는 수월하며, 또 반발 또한 작다. 왜냐하면, 이것은 editor 자체를 바꾸라는 것 보다는 당위성이 충분하기 때문이다.)
code editor 환경의 예를 들면 다음과 같은 것이 있다. (너무 복잡한 규정은 잘 지켜지지도 않고, 반발만 살 수 있음을 명심해야 한다.)

- tab은 space replacement로 하되 size 4로 한다.
- 줄바꿈은 Unix style(LF)를 따른다.
- ... etc..

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

[From DWARF Specification Version 2.0]

* Ambiguity in the Spec.
At first, let's see followings.

[Extracted from spec. page 66]
DW_CFA_def_cfa_offset takes a single unsigned LEB128 argument representing an offset -- (*1). The required action is to define the current CFA rule to use the provided offset (but to keep the old register).

[Extracted from spec. page 105]
fde + 17 DW_CFA_def_cfa_offset (<fsize>/4) -- (*2) ; assuming <fsize> < 512

As you can see above, in (*1) argument is just an offset. But in (*2), <fsize> is divided by '4'. So, I think there is conflict in those part.

In 'libdwarf', as (*1), it uses offset value itself. But, dwarf information generated by ADS1.2 compiler is obeys rule (*2) - offset * 4 (data alignment factor).

* How can we get Die from PC without 'Arrange Section'.

In this case, we can get CU Die from CU Header. And then, the result of sorting them into 'lowpc' order, can be used.

* Optimizing out local stack variable.

Unlike static or global variable, dwarf defines valid range for the local stack variable. That is, stack variable is valid only in this range. This may make mismatch between code and dwarf information; Sometimes, we seem to know value of variable when we look at the code, but in actual dwarf information, the variable is not valid yet, or optimized out. So, we cannot know it. Yes, this is totally compiler dependent.

Here is example.

funcA(...)
{
    int a = 8;
    ...
    a = 10;   // --- (*)
    ...
}

"int a=8" is stored at NVRAM. So, compiler don't need to keep this value in memory. Therefore, before "a=10;", this value may not be assigned into the stack - that is, there is not relative dwarf information. As a result, we cannot read value "a" by reading register of memory. (In practice, this kind of stuffs often happens in ADS1.2 compiler.)

* Handling included source.
See follows.

a.c
    ...

b.c
    ...
    #include "a.c"
    ...

(ASSUMPTION : 'a.c' is not compiled separately)

In ADS1.2, 10th line of 'a.c' is regarded as 10th line of 'b.c'. So, there are two 10th lines in the dwarf information. I think some compiler may handle this case correctly. But, in ADS1.2, dwarf information is generated unexpectedly.

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

When compare values, try to put constant or returned value from function call into left side - make it as l-value.
This habit can prevent you from mistake - using '=' instead of '=='.
(Compiler can detect this error(mistake)!)

#define X_VAL (100)
...
if( a == X_VAL ) { ... } // This is not good!
if( X_VAL == a) { ... } // Better

+ Recent posts