{ Start of file GPrimesD.PAS ***********************************************} {$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,R-,S+,V+,X-} { Pascal defaults } {$M 16384,0,655360} {$N+} { Uses numeric coprocessor } program GPrimesD; { Plots Gaussian primes } uses Crt, Graph; { Turbo Pascal interface } const Name = 'GPrimesD - Plots Gaussian primes'; Version = 'Version 1.00, last revised: 97/01/17, 1500 hours'; Author = 'Copyright (c) 1997 by author: Harry J Smith,'; Address = '19628 Via Monte Dr., Saratoga CA 95070. All rights reserved.'; {***************************************************************************} { Developed in TURBO Pascal 6.0 } { This program was inspired by the article "Complex Gaussian Integers for 'Gaussian Graphs'" by Henry G. Baker, ACM Sigplan Notices 28, 11 (Nov 1993), 22-27. Found on the WWW at URL ftp://ftp.netcom.com/pub/hb/hbaker/ Gaussian.html. It is similar to the program PTriplesP.Pas that plotted primitive Pythagorean triples. } type ColorType = 0 .. MaxColors; { Turbo Pascal type for colors } Reals = Double; { Change Double to Real if no coprocessor } const ESC = Char(27); var a : Reals; { a of (a, b, c) primitive Pythagorean triples } b : Reals; { b of (a, b, c) primitive Pythagorean triples } i : Integer; { Loop index } Ch : Char; { Character read from keyboard } { Graphics variables } AspectR : Reals; { Aspect ratio, EGA Hi = 10000 / 7750 = 1.2903225806 } XAsp : Word; { Horizontal aspect } YAsp : Word; { Vertical aspect } S : Reals; { Length of bottom side of rectangle } IS : LongInt; { S as an integer } h : Reals; { Height of rectangle } SlopeX : Reals; { Slope of transform of X to pixels } SlopeY : Reals; { Slope of transform of Y to pixels } X0 : Reals; { X of point in transform of X to pixels } Xp0 : Reals; { Xp of point in transform of X to pixels } Y0 : Reals; { Y of point in transform of Y to pixels } Yp0 : Reals; { Yp of point in transform of Y to pixels } Xp : Integer; { X in pixels } Yp : Integer; { Y in pixels } Border : Reals; { Size of border on screen in X pixels } Mess : String; { Character string for message to screen } Device : Integer; { Turbo Pascal graphics device code } Mode : Integer; { Turbo Pascal graphics device mode code } MaxXPix : Word; { Max pixel number in X direction, [0, MaxXPix] } MaxYPix : Word; { Max pixel number in Y direction, [0, MaxYPix] } Color : ColorType; { Turbo Pascal color code } Palette : PaletteType; { Turbo Pascal color palette } PrevX : Integer; { Previous X in pixels } PrevY : Integer; { Previous Y in pixels } {--------------------------------------} procedure ExitProc; { Exit the program } begin RestoreCrtMode; CloseGraph; Halt(0); end; { ExitProc } {--------------------------------------} function ForceColor( Color : ColorType) : ColorType; begin Color:= Color mod Palette.Size; IF Color = 0 then Color:= 1; SetColor( Color); ForceColor:= Color; end; { ForceColor } {--------------------------------------} procedure ReadLInt( Mess : String; Min, Max, Nom : LongInt; var II : LongInt); { Read in a long integer from keyboard } var St : String[255]; Stat : Integer; LI : LongInt; I : Integer; begin repeat repeat WriteLn( Mess); Write( ' [', Min, ', ', Max, '] (ENTER => ', Nom, '): '); ReadLn( St); WriteLn( St); until IOResult = 0; Val( St, LI, Stat); until ((Stat = 0) and (LI >= Min) and (LI <= Max)) or (Length(St) = 0); if Length( St) = 0 then LI:= Nom; II:= LI; WriteLn( 'Input = ', II); WriteLn; end; { ReadLInt } {--------------------------------------} procedure InitHead; { Initialize program } begin TextBackground( Blue); TextColor( Yellow); ClrScr; WriteLn; WriteLn; WriteLn( Name); WriteLn( Version); WriteLn( Author); WriteLn( Address); WriteLn; WriteLn('While plotting, press any key to pause, or ESC to exit'); WriteLn; end; { InitHead } {--------------------------------------} procedure Init2; { Initialize program, 2nd part } begin RestoreCrtMode; InitHead; WriteLn('Device, Mode, MaxX, MaxY = ', Device, ' ', Mode, ' ', MaxXPix, ' ', MaxYPix); Write('Palette.Size: Colors = ', Palette.Size, ':'); FOR I:= 0 TO Palette.Size-1 DO Write(' ', Palette.Colors[I]); { Show hardware information } WriteLn; WriteLn('Screen pixel aspect ratio = ', AspectR:0:9); WriteLn; WriteLn('Type any key to continue... (or Esc to quit)'); WriteLn; Ch:= ReadKey; if Ch = Chr(27) then ExitProc; WriteLn; Mess:= 'Input largest x or y to be displayed, 0 => 24, S = ? '; ReadLInt( Mess, 0, 200, 24, IS); S:= IS; if (S = 0) then S:= 24.0; h:= 2 * S; Border:= 0.0375 * MaxXPix; SetGraphMode( Mode); IF Palette.Size > 8 then SetBkColor( Black); Color:= ForceColor( White); end; { Init2 } {--------------------------------------} procedure Init; { Initialize program, can only do once } begin InitHead; { Init header before and after InitGraph, InitGraph may hang } Device:= Detect; Mode:= 0; InitGraph( Device, Mode, ''); { Determine type of graphics device } MaxXPix:= GetMaxX; MaxYPix:= GetMaxY; { and initialize graphics } GetAspectRatio( XAsp, YAsp); AspectR:= YAsp / XAsp; GetPalette( Palette); IF Palette.Size < 2 then Palette.Size:= 2; Init2; end; { Init } {--------------------------------------} function TranX( X : Reals) : Integer; { Transform X to Pixels } begin PrevX:= Round((X - X0) * SlopeX + Xp0); TranX:= PrevX; end; { TranX } {--------------------------------------} function TranY( Y : Reals) : Integer; { Transform Y to Pixels } begin PrevY:= Round((Y - Y0) * SlopeY + Yp0); TranY:= PrevY; end; { TranY } {--------------------------------------} function Prime( P : LongInt) : Boolean; { Is P a Prime } var I, R, Q : LongInt; begin Prime:= TRUE; if P = 3 then Exit; I:= 1; repeat I:= I + 2; Q:= P div I; R:= P - I * Q; if R = 0 then begin Prime:= False; Exit; end; until I > Q; end; { Prime } {--------------------------------------} procedure CompTran; { Compute constants for transforms to pixels } { Using point-slope form of linear transform } begin SlopeX:= (1.0 + MaxXPix - 2.0 * Border) / h; X0:= 0; Xp0:= (1.0 + MaxXPix) / 2.0; SlopeY:= -SlopeX / AspectR; Y0:= 0; Yp0:= (1.0 + MaxYPix) / 2.0; if (h > 10.0) or (TranY( h) * AspectR < Border) then begin SlopeY:= -(1 + MaxYPix - 2.0 * Border / AspectR) / h; Y0:= 0; Yp0:= (1.0 + MaxYPix) / 2.0; SlopeX:= -SlopeY * AspectR; X0:= 0; Xp0:= (1.0 + MaxXPix) / 2.0; end; if ( 0.99 < SlopeX) and (SlopeX < 1.01) then SlopeX:= 1.0; if (-1.01 < SlopeY) and (SlopeY < -0.99) then SlopeY:= -1.0; if (SlopeX > 3) then SlopeX:= 2 * Int( (SlopeX - 1) / 2) + 1; if (SlopeY < -3) then SlopeY:= -2 * Int( Abs((SlopeY + 1) / 2)) - 1; end; { CompTran } {--------------------------------------} procedure PlotSq( a, b : Reals); { Plot 1 square from a, b } var Sq : array[1..4] of PointType; d : Reals; begin d:= (S - 1) / (2 * S); Sq[1].x:= TranX(a - d); Sq[1].y:= TranY(b - d); Sq[2].x:= TranX(a + d); Sq[2].y:= TranY(b - d); Sq[3].x:= TranX(a + d); Sq[3].y:= TranY(b + d); Sq[4].x:= TranX(a - d); Sq[4].y:= TranY(b + d); FillPoly(4, Sq); end; { PlotSq } {--------------------------------------} procedure Plot( a, b : Reals); { Plot 8 points from a, b } begin PlotSq( a, b); { Plot a Square } PlotSq( b, a); PlotSq(-a, b); PlotSq(-b, a); PlotSq(-a, -b); PlotSq(-b, -a); PlotSq( a, -b); PlotSq( b, -a); end; { Plot } {--------------------------------------} procedure SearchP; { Search for Gaussian primes } var IS, P : LongInt; begin MoveTo( 10, TextHeight('M') + 3); IS:= Trunc(S); Plot(1, 1); P:= 1; repeat repeat repeat { Get next prime P} P:= P + 2; until Prime(P); if (P mod 4 = 3) then begin if (P < IS) then Plot(P, 0); end; until (P mod 4 = 1); a:= 0; { Reduce Prime integer P = 4*k + 1 to a^2 + b^2 } repeat a:= a + 1; b:= INT( SQRT( P - a * a)); until (P = a * a + b * b) or (a>b); if (a < IS) and (b < IS) and (a ESC) then Ch:= ReadKey; { Pause } end; if (Ch = ESC) then begin { If ESC typed } a:= IS + 1; b:= IS + 1; { Break out of loops } end; end; until (a > IS) and (b > IS); while (Ch <> ESC) do Ch:= ReadKey; { Pause } end; { SearchP } {--------------------------------------} begin { Main program, PTripleP } Init; { Initialize program } repeat CompTran; { Compute constants for transforms } MoveTo( TranX(-S), TranY(-S)); { Draw an 2S by 2S square } LineTo( TranX(-S), TranY( S)); LineTo( TranX( S), TranY( S)); LineTo( TranX( S), TranY(-S)); LineTo( TranX(-S), TranY(-S)); a:= -S; repeat b:= -S; repeat MoveTo( TranX(a), TranY(b)); { Plot a point } LineTo( PrevX, PrevY); b:= b + 1.0; until (b >= S); a:= a + 1.0; while (Keypressed) do begin { If key pressed } Ch:= ReadKey; if (Ch <> ESC) then Ch:= ReadKey; { Pause } end; if (Ch = ESC) then begin { If ESC typed } a:= S + 1; b:= S + 1; { Break out of loops } end; until (a >= S); MoveTo( 10, 1); Str(S:0:0, Mess); OutText('Plot of Gaussian primes, max x, y < ' + Mess + ':'); SearchP; Init2; { Re-initialize program } until False; end. { PTripleP } { End of file GPrimesD.PAS *************************************************}