It will generate a picture something like this[but with color] [https://upload.wikimedia.org/wikipedia/commons/f/f8/Sierpinski_m100000.png](https://upload.wikimedia.org/wikipedia/commons/f/f8/Sierpinski_m100000.png)
I wrote it first, a perl script: #!/usr/bin/perl use Cairo; my $size = 2000; my $border = 10; my $level = 12; my $image = 'perl.png'; my $surface = Cairo::ImageSurface->create( 'argb32', $size, $size ); my $cr = Cairo::Context->create($surface); sub X() { 0 } sub Y() { 1 } sub head() { 0 } sub left() { 1 } sub right() { 2 } sub some { $level, @_ } sub triangle { my $x = $size / 2 - $border; my $y = $x * sqrt 3; my $v = ( $size - $y ) / 2; my $triangle = [ [ $size / 2, $v ], [ $border, $size - $v ], [ $size - $border, $size - $v ] ]; [$triangle] } sub fill { my ( $left, $right, $tail ) = @_; my @color = ( ( $size - $tail->[Y] ) / $size, ( $size - $tail->[X] ) / $size, $tail->[X] / $size ); $cr->set_source_rgb(@color); $cr->move_to(@$left); $cr->line_to(@$right), $cr->line_to(@$tail); $cr->fill; } sub draw { my ( $level, $triangle ) = @_; return unless $level; my $x = ( $triangle->[0][head][X] - $triangle->[0][left][X] ) / 2; return if $x < 1; my $y = ( $triangle->[0][left][Y] - $triangle->[0][head][Y] ) / 2; my @next = map { my ( $HEAD, $LEFT, $RIGHT ) = @$_; my $left = [ $HEAD->[X] - $x, $HEAD->[Y] + $y ]; my $right = [ $HEAD->[X] + $x, $HEAD->[Y] + $y ]; my $tail = [ $HEAD->[X], $LEFT->[Y] ]; fill $left, $right, $tail; [ $HEAD, $left, $right ], [ $left, $LEFT, $tail ], [ $right, $tail, $RIGHT ] } @$triangle; draw( $level - 1, \@next ); } sub go { $cr->rectangle( 0, 0, $size, $size ); $cr->fill; $cr->set_line_width(.5); draw some triangle; $surface->write_to_png($image); } go; and then. I translate it to nim: import math, cairo type point = tuple[x, y: float] type trian = tuple[head, left, right: point] type trias = seq[trian] let size : float = 2000 border: float = 10 level = 12 image = "nim.png" var surface: PSurface cr: PContext proc triangle: trian = let x = size / 2.0 - border let y = x * 3.float64.sqrt let v = (size - y) / 2.0 ((size / 2.0, v), (border, size - v), (size - border, size - v)) proc fill(left, right, tail: point) = let r = ( size - tail.y ) / size g = ( size - tail.x ) / size b = tail.x / size cr.set_source_rgb(r, g, b) cr.move_to(left.x, left.y) cr.line_to(right.x, right.y) cr.line_to(tail.x, tail.y) cr.fill proc draw(level: int, ts: trias): trias = if level == 0: return let x = (ts[0].head.x - ts[0].left.x) / 2.0 if x < 1.0: return let y = (ts[0].left.y - ts[0].head.y) / 2.0 var next: trias for it in ts: let (HEAD, LEFT, RIGHT) = it let left = (HEAD.x - x, HEAD.y + y) let right = (HEAD.x + x, HEAD.y + y) let tail = (HEAD.x, LEFT.y) fill left, right, tail next = next & @[(HEAD, left, right), (left, LEFT, tail), (right, tail, RIGHT)] draw( level - 1, next ) proc go = let SIZE = size.int32 surface = image_surface_create(TFORMAT.FORMAT_ARGB32, SIZE, SIZE) cr = surface.create cr.rectangle(0, 0, size, size) cr.fill cr.set_line_width 0.5 let t1 = @[triangle()] discard draw(level, t1) discard surface.write_to_png image go() the time: perl: 2.3s nim: 9.0s [--cc=gcc, -d:release] My question is: 1: Why it is so slow? my nim code. 2: How to speed up my nim code?