First, I would like to apologize. My tone did cross a line, and I'm
sincerely sorry.
Apology accepted. Thanks.
.....
My question is this:
Do you think that, if this is infringement, that /1/ is necessarily also
infringement? How about /2/? I think that if the first is, both my
examples are as well, and that's why i'm uncomfortable with the position
that the first is.
1/return _M_d2i(&x,0) >= 0 || x <= 0 ? x : x+1;
2/
if(__dI(&x,0)<0 && x > 0)
return x+1.;
else
return x;
You can fuzz the line until the cows come home. My initial
observation was that the one-liner ceil was pretty clearly
infringing in its own right because:
a) it differed only in whitespace and redundant parens from the
expression I used, down to the funny name for the internal function
_Dint, and
b) it was built around an inventive approach to ceil that I've
never seen in another implementation (down to the nuts and bolts,
even though said nuts and bolts did not appear in the one-liner)
Changing names is a step away, as is restating the algorithm.
How far is far enough? Operationally, it's probably when you've
made enough changes that you have a new debugging task on your
hands, and you're not just piggybacking on the testing and
debugging done for the prototype that inspired you. I don't
pretend it's a bright line in general. But I think it was in
the originally presented particular case for ceil.
I think mine would too, but i'd think of it as being strong evidence of
further 'lifting' rather than being copyright infringement in itself -
Uh, to me that's a distinction without a difference. You still
seem to think that infringement only occurs after a certain
number of yards of code have been replicated. In literature,
you can infringe:
a book copyright by copying half a page without attribution or
permission
a screenplay by imitating the principal characters and plot outline
a poem by quoting one plangent line
It depends more on the creative freight than the length of the
train.
whatever you end up naming the macro, there's really only one way to
declare a cdecl function on gcc, and only one way to do so on msvc. /3/,
right?
No, there are several. Part of my point.
No idea what _CRTIMP does. dllexport? I'm certainly not
disagreeing that it should raise suspicion, just that it's copyright
infringement per se.
3/
#if defined(__GNUC__)
#define _CDECL __cdecl
#elif defined(WIN32)
#define _CDECL __attribute__((__cdecl__))
#endif
Good guess, but off the mark. The creativity can also come in
*where* you put the _CDECL decorations, as well as what they
expand to.
It's unlikely you're the first to think of bundling sine and cosine into
a single function.
Right, but making the second argument a quadrant offset is not
widely done. Nor is the naming convention. Nor, necessarily, is
the direct call to the common internal function from a C++ inline
and a C macro. etc. etc.
Again, the names very much should raise suspicion,
and I certainly didn't mean to fault you for that - but the core imple-
mentation itself would be the actual infringement. I think part of it is
that I strongly disagree that changing the names should have any effect
on whether it's copyright infringement or not, since identifiers aren't
really the expressive part of code. I'm sure you probably agree that if
someone stole your code it would be made any better if they ran it
through an obfuscator to change all the identifiers.
Sorry, but it's both. We all know that a good set of naming
conventions can materially aid the readability of code, and
hence contribute to its worth. At the same time, it's not
the whole value added, so mechanically altering the names
and retaining the code structure doesn't cut it either.
You can't say one aspect is the arena for determining
infringment and the other is not.
I think that if inline double _CDECL sin(double _Left) { return (_Sin
(_Left, 0)); } is infringement, it is implicit that inline double
__cdecl__ sin(double _M_angle) { return (_M_sin(_M_angle,0)); } must
also be. That is what makes me uncomfortable about your position.
Well, it doesn't have to. See above.
Yes, but in my opinion you'd have to look behind them, not in them, to
find the actual ripoff.
Another distinction without a difference. *Both* the foreground
and the background are part of the expression.
.....
Fine, but we don't. It became obvious only after lots of work and
rework on my part, some of it dating back over 40 years.
ceil itself did? The idea of having a _Dint() function [and the details
of its specification, etc] did? or are we talking about the implement-
ation of _Dint()? No offense intended, I'm just confused here.
IIRC, _Dint first arose as a safe way to perform the common operation
of ceil and floor, safely for large and semi-numeric values. It then
became apparent that several internal functions were so similar that
they should be merged, if only to lower the cost of porting. So
ceil and _Dint evolved back and forth, not in any simply directed
fashion (as top-down advocates would have you believe).
You're lucky that I chose to take a walk to Starbucks before replying
to this post. You pervert what I actually said, then use it as an
excuse to accuse *me* of being dishonest. Nary a word against the
clear-cut case of infringement that's there for anyone with a copy
of my book to verify.
Sorry - I don't have a copy of your book so I didn't feel qualified to
comment on that in either direction. I still don't believe that there's
that much variation possible in ceil() itself, and i hadn't even looked
at either the _Dint implementation on there, or, obviously, yours [since
i don't have the book]
I just grabbed three implementations of ceil from glibc. (There are
about two dozen.) They're attached below. Which one do you think looks
most like my implementation?
P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
----
double
__ceil (double x)
{
if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */
{
double tmp1, new_x;
new_x = -x;
__asm (
#ifdef _IEEE_FP_INEXACT
"cvttq/svim %2,%1\n\t"
#else
"cvttq/svm %2,%1\n\t"
#endif
"cvtqt/m %1,%0\n\t"
: "=f"(new_x), "=&f"(tmp1)
: "f"(new_x));
/* Fix up the negation we did above, as well as handling -0 properly.
*/
x = copysign(new_x, x);
}
return x;
}
----
#include <machine/asm.h>
RCSID("$NetBSD: s_ceil.S,v 1.4 1995/05/08 23:52:13 jtc Exp $")
ENTRY(__ceil)
fldl 4(%esp)
subl $8,%esp
fstcw 4(%esp) /* store fpu control word */
/* We use here %edx although only the low 1 bits are defined.
But none of the operations should care and they are faster
than the 16 bit operations. */
movl $0x0800,%edx /* round towards +oo */
orl 4(%esp),%edx
andl $0xfbff,%edx
movl %edx,(%esp)
fldcw (%esp) /* load modified control word */
frndint /* round */
fldcw 4(%esp) /* restore original control word */
addl $8,%esp
ret
----
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double huge = 1.0e300;
#else
static double huge = 1.0e300;
#endif
#ifdef __STDC__
double __ceil(double x)
#else
double __ceil(x)
double x;
#endif
{
int32_t i0,i1,j0;
u_int32_t i,j;
EXTRACT_WORDS(i0,i1,x);
j0 = ((i0>>20)&0x7ff)-0x3ff;
if(j0<20) {
if(j0<0) { /* raise inexact if x != 0 */
if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
if(i0<0) {i0=0x80000000;i1=0;}
else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;}
}
} else {
i = (0x000fffff)>>j0;
if(((i0&i)|i1)==0) return x; /* x is integral */
if(huge+x>0.0) { /* raise inexact flag */
if(i0>0) i0 += (0x00100000)>>j0;
i0 &= (~i); i1=0;
}
}
} else if (j0>51) {
if(j0==0x400) return x+x; /* inf or NaN */
else return x; /* x is integral */
} else {
i = ((u_int32_t)(0xffffffff))>>(j0-20);
if((i1&i)==0) return x; /* x is integral */
if(huge+x>0.0) { /* raise inexact flag */
if(i0>0) {
if(j0==20) i0+=1;
else {
j = i1 + (1<<(52-j0));
if(j<i1) i0+=1; /* got a carry */
i1 = j;
}
}
i1 &= (~i);
}
}
INSERT_WORDS(x,i0,i1);
return x;
}