Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8212ad2

Browse files
Merge branch 'feature/20-add-ieee-pown-functions' into develop
Fixes #20
2 parents b5026e9 + 0f2d7df commit 8212ad2

File tree

6 files changed

+241
-0
lines changed

6 files changed

+241
-0
lines changed

‎collection/633.dat‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
function PowN(const X: Extended; const N: Integer): Extended;
2+
var
3+
I: Integer;
4+
begin
5+
if N = 0 then
6+
// IEEE: pown(x, 0) is 1, even when X is zero
7+
Exit(1.0);
8+
if Math.SameValue(1.0, X) then
9+
Exit(1.0);
10+
if Math.IsZero(X) then
11+
begin
12+
if N < 0 then
13+
raise SysUtils.EDivByZero.Create('PowN: Negative exponent for X = 0');
14+
Exit(0.0);
15+
end;
16+
Result := 1.0;
17+
for I := 1 to System.Abs(N) do
18+
Result := Result * X;
19+
if N < 0 then
20+
Result := 1 / Result;
21+
end;

‎collection/634.dat‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function PowNZN(const X: Integer; const N: Cardinal): Int64;
2+
var
3+
I: Integer;
4+
begin
5+
if (X = 0) and (N > 0) then
6+
Exit(0);
7+
if X = 1 then
8+
Exit(1);
9+
Result := 1;
10+
for I := 1 to N do
11+
Result := Result * X;
12+
end;

‎collection/635.dat‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
function PowNZZ(const X: Integer; const N: Integer): Extended;
2+
var
3+
I: Integer;
4+
ResultInt: Int64;
5+
begin
6+
if N = 0 then
7+
Exit(1.0);
8+
if X = 1 then
9+
Exit(1.0);
10+
if X = 0 then
11+
begin
12+
if N < 0 then
13+
raise SysUtils.EDivByZero.Create('PowNZZ: Negative exponent for X = 0');
14+
Exit(0.0);
15+
end;
16+
ResultInt := 1;
17+
for I := 1 to System.Abs(N) do
18+
ResultInt := ResultInt * X;
19+
if N > 0 then
20+
Result := ResultInt
21+
else // N < 0
22+
Result := 1 / ResultInt;
23+
end;

‎collection/maths.ini‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,7 @@ FPC=Y
11781178

11791179
[Pow]
11801180
DescEx="<p>Raises integer value <var>Base</var> to non-negative integer power <var>Exponent</var> and returns the result.</p>"
1181+
SeeAlso=PowN,PowNZN,PowNZZ
11811182
Snip=561.dat
11821183
Delphi2=N
11831184
Delphi3=N
@@ -1197,6 +1198,44 @@ DelphiXE4=Y
11971198
Delphi10S=Y
11981199
FPC=Y
11991200

1201+
[PowN]
1202+
DescEx="<p>IEEE compliant function that raises real number <var>X</var> to the power <var>N</var>.</p>"
1203+
Extra="<p>See IEEE standard 754-2008 for Floating-Point Arithmetic, page 44.</p>"
1204+
Units=SysUtils,Math
1205+
SeeAlso=Pow,PowNZN,PowNZZ
1206+
TestInfo=advanced
1207+
AdvancedTest.Level=unit-tests
1208+
AdvancedTest.URL="https://github.com/delphidabbler/code-snippets/tree/master/tests/Cat-Maths"
1209+
Snip=633.dat
1210+
DelphiXE=Y
1211+
Delphi11A=Y
1212+
Delphi12A=Y
1213+
1214+
[PowNZN]
1215+
DescEx="<p>Raises integer <var>X</var> to non-negative integer power <var>N</var>.</p>"
1216+
Extra="<p>Returns an <var>integer</var> value because the power <var>N</var> is non-negative which guarantees that the result is integral.</p><p>Based on IEEE standard 754-2008 for Floating-Point Arithmetic, page 44, but which restricts <var>X</var> to an integer and <var>N</var> to a non-negative integer.</p>"
1217+
SeeAlso=Pow,PowN,PowNZZ
1218+
TestInfo=advanced
1219+
AdvancedTest.Level=unit-tests
1220+
AdvancedTest.URL="https://github.com/delphidabbler/code-snippets/tree/master/tests/Cat-Maths"
1221+
Snip=634.dat
1222+
DelphiXE=Y
1223+
Delphi11A=Y
1224+
Delphi12A=Y
1225+
1226+
[PowNZZ]
1227+
DescEx="<p>Raises integer <var>X</var> to integer power <var>N</var>.</p>"
1228+
Extra="<p>Returns an <var>Extended</var> value since the result is not an integer when power <var>N</var> is negative.</p><p>Based on IEEE standard 754-2008 for Floating-Point Arithmetic, page 44, but which restricts <var>X</var> to an integer.</p>"
1229+
Units=SysUtils,
1230+
SeeAlso=Pow,PowN,PowNZN
1231+
TestInfo=advanced
1232+
AdvancedTest.Level=unit-tests
1233+
AdvancedTest.URL="https://github.com/delphidabbler/code-snippets/tree/master/tests/Cat-Maths"
1234+
Snip=635.dat
1235+
DelphiXE=Y
1236+
Delphi11A=Y
1237+
Delphi12A=Y
1238+
12001239
[ResizeRect_A]
12011240
DisplayName="ResizeRect (TSize overload)"
12021241
DescEx="<p>Resizes rectangle <var>R</var> to size <var>NewSize</var>, leaving the top-left position unchanged.</p><p>Returns the resized rectangle.</p>"

‎tests/Cat-Maths/TestUMathsCatSnippets.pas‎

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ TestMathsCatSnippets = class(TTestCase)
4040
procedure TestMaxOfArray_Single;
4141
procedure TestMaxOfArray_Double;
4242
procedure TestMaxOfArray_Extended;
43+
procedure TestPowNZN;
44+
procedure TestPowNZZ;
45+
procedure TestPowN;
4346
end;
4447

4548
implementation
@@ -530,6 +533,78 @@ procedure TestMathsCatSnippets.TestMinOfArray_Single;
530533
Check(SameValue(N, MinOfArray(A)), 'Test 5');
531534
end;
532535

536+
procedure TestMathsCatSnippets.TestPowN;
537+
begin
538+
CheckEquals(0, PowN(0, 2), 'PowN(0,2)');
539+
CheckEquals(1, PowN(42, 0), 'PowN(42,0)');
540+
CheckEquals(1, PowN(0, 0), 'PowN(0,0)');
541+
CheckEquals(1, PowN(1, 1), 'PowN(1,1)');
542+
CheckEquals(-1, PowN(-1, 1), 'PowN(-1,1)');
543+
CheckEquals(1, PowN(1, 5), 'PowN(1,5)');
544+
CheckEquals(4, PowN(2, 2), 'PowN(2,2)');
545+
CheckEquals(4, PowN(-2, 2), 'PowN(-2,2)');
546+
CheckEquals(100, PowN(10, 2), 'PowN(10,2)');
547+
CheckEquals(10000, PowN(10, 4), 'PowN(10,2)');
548+
CheckEquals(1.0, PowN(0, 0), 'PowN(0, 0)');
549+
CheckEquals(1/2, PowN(2, -1), 'PowN(2, -1)');
550+
CheckEquals(1/1000, PowN(10, -3), 'PowN(10, -3)');
551+
CheckEquals(-1000, PowN(-10, 3), 'PowN(-10, 3)');
552+
CheckEquals(-1/1000, PowN(-10, -3), 'PowN(-10, -3)');
553+
CheckEquals(4, PowN(2, 2), 'PowN(2,2)');
554+
CheckEquals(4, PowN(-2, 2), 'PowN(-2,2)');
555+
CheckEquals(1/27, PowN(3, -3), 'PowN(3, -3)');
556+
CheckEquals(1/3, PowN(3, -1), 'PowN(3, -1)');
557+
CheckEquals(-1, PowN(-1, -3), 'PowN(-1, -3)');
558+
CheckEquals(4294967296, PowN(2, 32), 'PowN(2, 32');
559+
// Floats
560+
CheckEquals(Math.Power(45.3672, 3.0), PowN(45.3672, 3), 'PowN(45.3672, 12)');
561+
CheckEquals(Math.Power(-0.87659, -7), PowN(-0.87659, -7), 'PowN(-0.87659, -7)');
562+
CheckEquals(Math.Power(45.3672, -3.0), PowN(45.3672, -3), 'PowN(45.3672, -3)');
563+
CheckEquals(Math.Power(-0.87659, -7), PowN(-0.87659, -7), 'PowN(-0.87659, -7)');
564+
CheckEquals(Math.Power(-0.87659, 3), PowN(-0.87659, 3), 'PowN(-0.87659, 3)');
565+
end;
566+
567+
procedure TestMathsCatSnippets.TestPowNZN;
568+
begin
569+
CheckEquals(0, PowNZN(0, 2), 'PowNZN(0,2)');
570+
CheckEquals(1, PowNZN(42, 0), 'PowNZN(42,0)');
571+
CheckEquals(1, PowNZN(0, 0), 'PowNZN(0,0)');
572+
CheckEquals(1, PowNZN(1, 1), 'PowNZN(1,1)');
573+
CheckEquals(-1, PowNZN(-1, 1), 'PowNZN(-1,1)');
574+
CheckEquals(1, PowNZN(1, 5), 'PowNZN(1,5)');
575+
CheckEquals(4, PowNZN(2, 2), 'PowNZN(2,2)');
576+
CheckEquals(4, PowNZN(-2, 2), 'PowNZN(-2,2)');
577+
CheckEquals(100, PowNZN(10, 2), 'PowNZN(10,2)');
578+
CheckEquals(10000, PowNZN(10, 4), 'PowNZN(10,2)');
579+
CheckEquals(-1000, PowNZN(-10, 3), 'PowNZN(-10,3)');
580+
CheckEquals(10000, PowNZN(-10, 4), 'PowNZN(-10,4)');
581+
end;
582+
583+
procedure TestMathsCatSnippets.TestPowNZZ;
584+
begin
585+
CheckEquals(0, PowNZZ(0, 2), 'PowNZZ(0,2)');
586+
CheckEquals(1, PowNZZ(42, 0), 'PowNZZ(42,0)');
587+
CheckEquals(1, PowNZZ(0, 0), 'PowNZZ(0,0)');
588+
CheckEquals(1, PowNZZ(1, 1), 'PowNZZ(1,1)');
589+
CheckEquals(-1, PowNZZ(-1, 1), 'PowNZZ(-1,1)');
590+
CheckEquals(1, PowNZZ(1, 5), 'PowNZZ(1,5)');
591+
CheckEquals(4, PowNZZ(2, 2), 'PowNZZ(2,2)');
592+
CheckEquals(4, PowNZZ(-2, 2), 'PowNZZ(-2,2)');
593+
CheckEquals(100, PowNZZ(10, 2), 'PowNZZ(10,2)');
594+
CheckEquals(10000, PowNZZ(10, 4), 'PowNZZ(10,2)');
595+
CheckEquals(1.0, PowNZZ(0, 0), 'PowNZZ(0, 0)');
596+
CheckEquals(1/2, PowNZZ(2, -1), 'PowNZZ(2, -1)');
597+
CheckEquals(1/1000, PowNZZ(10, -3), 'PowNZZ(10, -3)');
598+
CheckEquals(-1000, PowNZZ(-10, 3), 'PowNZZ(-10, 3)');
599+
CheckEquals(-1/1000, PowNZZ(-10, -3), 'PowNZZ(-10, -3)');
600+
CheckEquals(4, PowNZZ(2, 2), 'PowNZZ(2,2)');
601+
CheckEquals(4, PowNZZ(-2, 2), 'PowNZZ(-2,2)');
602+
CheckEquals(1/27, PowNZZ(3, -3), 'PowNZZ(3, -3)');
603+
CheckEquals(1/3, PowNZZ(3, -1), 'PowNZZ(3, -1)');
604+
CheckEquals(-1, PowNZZ(-1, -3), 'PowNZZ(-1, -3)');
605+
CheckEquals(4294967296, PowNZZ(2, 32), 'PowNZZ(2, 32');
606+
end;
607+
533608
procedure TestMathsCatSnippets.TestResizeRect_A;
534609
var
535610
R: Types.TRect;

‎tests/Cat-Maths/UMathsCatSnippets.pas‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,15 @@ function Pow(const Base: Int64; const Exponent: Byte): Int64;
219219
{Raises integer value Base to non-negative integer power Exponent and returns
220220
the result.}
221221

222+
function PowN(const X: Extended; const N: Integer): Extended;
223+
{IEEE compliant function that raises real number X to the power N.}
224+
225+
function PowNZZ(const X: Integer; const N: Integer): Extended;
226+
{Raises integer X to non-negative integer power N.}
227+
228+
function PowNZN(const X: Integer; const N: Cardinal): Int64;
229+
{Raises integer X to integer power N.}
230+
222231
function RectArea(const R: Windows.TRect): Int64;
223232
{Returns the area of the given rectangle.}
224233

@@ -1026,6 +1035,68 @@ function Pow(const Base: Int64; const Exponent: Byte): Int64;
10261035
Result := Result * Base;
10271036
end;
10281037

1038+
function PowN(const X: Extended; const N: Integer): Extended;
1039+
{IEEE compliant function that raises real number X to the power N.}
1040+
var
1041+
I: Integer;
1042+
begin
1043+
if N = 0 then
1044+
// IEEE: pown(x, 0) is 1, even when X is zero
1045+
Exit(1.0);
1046+
if Math.SameValue(1.0, X) then
1047+
Exit(1.0);
1048+
if Math.IsZero(X) then
1049+
begin
1050+
if N < 0 then
1051+
raise SysUtils.EDivByZero.Create('PowN: Negative exponent for X = 0');
1052+
Exit(0.0);
1053+
end;
1054+
Result := 1.0;
1055+
for I := 1 to System.Abs(N) do
1056+
Result := Result * X;
1057+
if N < 0 then
1058+
Result := 1 / Result;
1059+
end;
1060+
1061+
function PowNZN(const X: Integer; const N: Cardinal): Int64;
1062+
{Raises integer X to integer power N.}
1063+
var
1064+
I: Integer;
1065+
begin
1066+
if (X = 0) and (N > 0) then
1067+
Exit(0);
1068+
if X = 1 then
1069+
Exit(1);
1070+
Result := 1;
1071+
for I := 1 to N do
1072+
Result := Result * X;
1073+
end;
1074+
1075+
function PowNZZ(const X: Integer; const N: Integer): Extended;
1076+
{Raises integer X to non-negative integer power N.}
1077+
var
1078+
I: Integer;
1079+
ResultInt: Int64;
1080+
begin
1081+
if N = 0 then
1082+
Exit(1.0);
1083+
if X = 1 then
1084+
Exit(1.0);
1085+
if X = 0 then
1086+
begin
1087+
if N < 0 then
1088+
raise SysUtils.EDivByZero.Create('PowNZZ: Negative exponent for X = 0');
1089+
Exit(0.0);
1090+
end;
1091+
ResultInt := 1;
1092+
for I := 1 to System.Abs(N) do
1093+
ResultInt := ResultInt * X;
1094+
if N > 0 then
1095+
Result := ResultInt
1096+
else // N < 0
1097+
Result := 1 / ResultInt;
1098+
end;
1099+
10291100
function RectArea(const R: Windows.TRect): Int64;
10301101
{Returns the area of the given rectangle.}
10311102
begin

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /