// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Micro-benchmarks for copying typed data lists.

import 'dart:typed_data';

import 'package:benchmark_harness/benchmark_harness.dart';

abstract class Uint8ListCopyBenchmark extends BenchmarkBase {
  final int size;
  late Uint8List input;
  late Uint8List result;

  Uint8ListCopyBenchmark(String method, this.size)
      : super('TypedDataDuplicate.Uint8List.$size.$method');

  @override
  void setup() {
    input = Uint8List(size);
    for (var i = 0; i < size; ++i) {
      input[i] = (i + 3) & 0xff;
    }
  }

  @override
  void warmup() {
    for (var i = 0; i < 100; ++i) {
      run();
    }
  }

  @override
  void teardown() {
    for (var i = 0; i < size; ++i) {
      if (result[i] != ((i + 3) & 0xff)) {
        throw 'Unexpected result';
      }
    }
  }
}

class Uint8ListCopyViaFromListBenchmark extends Uint8ListCopyBenchmark {
  Uint8ListCopyViaFromListBenchmark(int size) : super('fromList', size);

  @override
  void run() {
    result = Uint8List.fromList(input);
  }
}

class Uint8ListCopyViaLoopBenchmark extends Uint8ListCopyBenchmark {
  Uint8ListCopyViaLoopBenchmark(int size) : super('loop', size);

  @override
  void run() {
    final input = this.input;
    final result = Uint8List(input.length);
    for (var i = 0; i < input.length; i++) {
      result[i] = input[i];
    }
    this.result = result;
  }
}

abstract class Float64ListCopyBenchmark extends BenchmarkBase {
  final int size;
  late Float64List input;
  late Float64List result;

  Float64ListCopyBenchmark(String method, this.size)
      : super('TypedDataDuplicate.Float64List.$size.$method');

  @override
  void setup() {
    input = Float64List(size);
    for (var i = 0; i < size; ++i) {
      input[i] = (i - 7).toDouble();
    }
  }

  @override
  void teardown() {
    for (var i = 0; i < size; ++i) {
      if (result[i] != (i - 7).toDouble()) {
        throw 'Unexpected result';
      }
    }
  }
}

class Float64ListCopyViaFromListBenchmark extends Float64ListCopyBenchmark {
  Float64ListCopyViaFromListBenchmark(int size) : super('fromList', size);

  @override
  void run() {
    result = Float64List.fromList(input);
  }
}

class Float64ListCopyViaLoopBenchmark extends Float64ListCopyBenchmark {
  Float64ListCopyViaLoopBenchmark(int size) : super('loop', size);

  @override
  void run() {
    final input = this.input;
    final result = Float64List(input.length);
    for (var i = 0; i < input.length; i++) {
      result[i] = input[i];
    }
    this.result = result;
  }
}

void main() {
  final sizes = [8, 32, 256, 16384];
  final benchmarks = [
    for (int size in sizes) ...[
      Uint8ListCopyViaLoopBenchmark(size),
      Uint8ListCopyViaFromListBenchmark(size)
    ],
    for (int size in sizes) ...[
      Float64ListCopyViaLoopBenchmark(size),
      Float64ListCopyViaFromListBenchmark(size)
    ]
  ];
  for (var bench in benchmarks) {
    bench.report();
  }
}
