### 1. Leap Years

```Does anyone have an algorithm for determining whether or not a given year is
a leap year? (Sorry, this has probably been asked and answered before.)

Joshua Milligan
```

### 2. Re: Leap Years

```On Sun, 1 Mar 1998, Joshua Milligan wrote:

> Does anyone have an algorithm for determining whether or not a given year is
> a leap year? (Sorry, this has probably been asked and answered before.)
>
> Joshua Milligan
>

--
Ryan Zerby, Senior Programmer   ryanz at netrex.com
"to create out of his own imagination the beauty of his wild forebears
--a mythology he cannot inherit." -- Allen Ginsberg 'Wild Orphan'
```

### 3. Re: Leap Years

```Joshua Milligan wrote:
>
> Does anyone have an algorithm for determining whether or not a given year is
> a leap year? (Sorry, this has probably been asked and answered before.)
>
> Joshua Milligan

------------------------------------------------------------------------------
-- leap year is any year divisible by 4, as long as...
-- it is not divisible by 100 unless it's divisible by 400
-- as well.

function leap_year (atom year)
-- returns 1 for leap years, 0 for non-leap years
return (remainder(year, 4) = 0) and
(remainder(year, 100) != 0) or
(remainder(year, 400) = 0)
end function
------------------------------------------------------------------------------

Hope this helps,
Christopher D. Hickman
```

### 4. Re: Leap Years

```Here's a lean version of leap year testing.  I don't know how it
compares to others on speed.
----------------
global function leap_year(integer y)
-- return 1 for leap year, 0 for not
return  ( integer(y/4)*(not integer(y/100)) + integer(y/400) )
end function
----------------

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
J. Craig Gilbert
cgilbert at mc.peachnet.edu
"Positing infinity, the rest is easy."
Roger Zelazny, in
'Creatures of Light and Darkness'
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
```

### 5. Re: Leap Years

```Craig wrote:
>
> Here's a lean version of leap year testing.  I don't know how it
> compares to others on speed.
> ----------------
> global function leap_year(integer y)
> -- return 1 for leap year, 0 for not
>    return  ( integer(y/4)*(not integer(y/100)) + integer(y/400) )
> end function
> ----------------
>
First off, let me say that I don't think this is a function that really
warrants much attention as far as optimization. But, I do like to play
with optimization to improve my techniques, so I compared this function
against the one I posted earlier just to see what the difference would
be.
The one I posted actually clocked at over 5 times faster than this
version.
This is probably due to your use of division. Division is the most
expensive
in machine cycles of the simple math operators. When speed is crucial,
it
should be avoided if possible. Many game programming books contain
lengthy
discussions just on techniques to avoid division.

Christopher D. Hickman
```

### 6. Re: Leap Years

```Christopher wrote:
> Craig wrote:
> >
> > Here's a lean version of leap year testing.  I don't know how it
> > compares to others on speed.
> > ----------------
> > global function leap_year(integer y)
> > -- return 1 for leap year, 0 for not
> >    return  ( integer(y/4)*(not integer(y/100)) + integer(y/400) )
> > end function
> > ----------------
> >
> <SKIPPED>
> The one I posted actually clocked at over 5 times faster than this
> version.
> This is probably due to your use of division. Division is the most
> expensive
> in machine cycles of the simple math operators. When speed is crucial,
> it
> should be avoided if possible. Many game programming books contain
> lengthy
> discussions just on techniques to avoid division.
>
> Christopher D. Hickman

Interesting!  I would not have guessed there would be as much
difference as that between a straight division and a remainder()
call.  I guess the combination of a straight division *and* a type
check call to integer() might be what did it.  Let me check . . .

Nope.  Just ran some tests; a division all by itself is still
slower than a remainder.  That strikes me as really odd; doesn't
it have to divide anyway to _find_ the remainder?  Oh, well.
Thanks, Christopher; now I've learned another quirk of
programming.

I tried some other comparisons, though, and found that
the type check does contribute to the problem as well . . . a type
check in this situation is actually slower than the remainder() call:

a = integer(.7)
is slower than
a = remainder(y,4)

The time jumped around a lot between being about the same (but still
slower) to being about twice as long.

So, I was dragging my code down all over the place, basically, with
both the type check and the division being slower individually than
the remainder() call and thus _much_ slower together.

One last note, which would not apply to the leap year routine:
a = integer(n)
is faster than
a = remainder(b, n)

I know that seems intuitively obvious, but I wanted to make sure
I wasn't giving the impression that I thought  remainder() is faster
than a type check on a level playing field.  It is most definitely
*not*; it's just that the respective  leapyear routines ended up
comparing remainder(b, <some integer> ) to integer(<some fraction>)
with, of course, the fraction coming from a division that is itself
slowing the whole shebang down.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
J. Craig Gilbert
cgilbert at mc.peachnet.edu
"Positing infinity, the rest is easy."
Roger Zelazny, in
'Creatures of Light and Darkness'
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
```

### 7. Re: Leap Years

```|Craig wrote:
|>
|> Here's a lean version of leap year testing.  I don't know how it
|> compares to others on speed.
|> ----------------
|> global function leap_year(integer y)
|> -- return 1 for leap year, 0 for not
|>    return  ( integer(y/4)*(not integer(y/100)) + integer(y/400) )
|> end function
|> ----------------

Two things,
This can be done faster, as the optimization page of Lucius L. Hilley
stated. (and the optimize.doc in our \doc directory of Euphoria 2beta)

Remainders of values of 2^n can be done with and_bits, and it will be about
3 times faster:
So, you would endup with:

global function leap_year(integer y)
-- return 1 for leap year, 0 for not
if and_bits (3,y) then
if remainder (y, 100) then
if remainder (y, 400) then
return 1
else
return 0
end if
else
return 1
end if
else
return 0
end if
end function

I haven't tested it, but it should be a lot faster.
Esspecially because I only call the other 2 remainder, when it is needed.
A short circuit like some1 asked, is a good idea, in an alternative syntax.

if length(s) thenif s = 1 then

... stuf..

elsif length(d) thenif d = 4 then

.. stuff..

end if

Here you state how the short-cut must be, however it is only a help-thingie,
which DOES bring more clearity to a program. Euphoria itself can never
decide to short-circuit, because you may call a routine after that, or do
something illegal, which simply does not add to the readablity of Euphoria.

And one more thing about optimizing by ex.exe:
When we have a long -if -elsif chain constantly checking the same variable,
could it be speed up a bit ?
It is now just as long as getting variable value, compare or whatever,
continue.

You might also be able to optimize a quick jump into the last slice used.
So that stuff like:

for index = 1 to length(s) do
s[index] = index^2        -- Yeah I know, I should use
power ()
end for

This can be optimized a lot, first of: the loop can be optimized by Euphoria
to jump through the sequence s. (set step of a secondaity index to the space
of an element and have the secondairy index count along.
Withing the code, the position  can have a precalculated offset, into
the sequence s.
All the type checking (to prevent errors from happening in this kind of
dangerous trick) should be done before the loop. (as I think it should
always be done).

Ralf
```

### 8. Re: Leap Years

```Craig wrote:

>Nope.  Just ran some tests; a division all by itself is still
>slower than a remainder.  That strikes me as really odd; doesn't
>it have to divide anyway to _find_ the remainder?  Oh, well.

No, I think internally the machine only subtracts to find a remainder.

```