演習問題とは言え、あまりにひどい内容で出すのもどうかと思い、ちょっとだけリファクタリング。
PS3のFC5は、デフォルトではLANGがen_US.UTF-8なので、自分の.bashrcでja_JP.eucJPにしたら、manとかで日本語が見れるようになった。(ひょっとしたらインストーラが聞いてきていたのかな?)
で、毎回gccのコマンドラインを打つのは面倒だし、オプションも覚えていられないので、以下の内容でMakefileを作成。
CC=gcc
CFLAGS=-maltivec -mabi=altivec
これで、たとえばp2-1.cがある状態で、
$ make p2-1
とかやればp2-1がコンパイルできる。コンパイルするものがあらかじめ決まっている場合は、Makefileに以下のような行を追加してやればmake一発で良い。
all: p2-1o p2-1 p2-2o p2-2 p2-3o p2-3 p2-4o p2-4
と、言うわけで演習問題の解答を見直してみる。

演習問題 (2-1)
#include <stdio.h>
#include <altivec.h>

/**
 * 整数の合計を計算する。
 * オーバーフローは考慮しない。
 * @param size 合計を計算する要素の数(4の倍数)
 * @param data 合計を計算する要素(16バイトアラインにそろっていること)
 * @return 合計
 */
int calc_sum(int size, int data[]) {
  int sum[4] __attribute__((aligned(16))) = {0, 0, 0, 0};
  int i;
  vector signed int *vdata = (vector signed int *) data;
  vector signed int *vsum = (vector signed int *) sum;

  for (i = 0; i < size / 4; i++) {
    *vsum = vec_add(*vsum, vdata[i]);
  }

  return sum[0] + sum[1] + sum[2] + sum[3];
}

#define MAX_NUM 1024

int main(int argc, char *argv[])
{
  int i;
  int data[MAX_NUM] __attribute__((aligned(16)));

  for (i = 0; i < MAX_NUM; i++) {
    data[i] = i + 1;
  }

  printf("%d\n", calc_sum(MAX_NUM, data));

  return 0;
}

演習問題 (2-2)
#include <stdio.h>
#include <altivec.h>

/**
 * in で渡されたsize個のデータを、0.5倍してoutに格納する。
 * @param size データの個数(8の倍数)
 * @param in データ
 * @param out in を0.5倍した結果
 */
void calc_half(int size, unsigned short in[], float out[]) {
  static vector unsigned short vzero;
  static vector unsigned char vpat[2] = {
    (vector unsigned char) {
      0x10, 0x10, 0x00, 0x01, 0x10, 0x10, 0x02, 0x03,
      0x10, 0x10, 0x04, 0x05, 0x10, 0x10, 0x06, 0x07,
    },
    (vector unsigned char) {
      0x10, 0x10, 0x08, 0x09, 0x10, 0x10, 0x0a, 0x0b,
      0x10, 0x10, 0x0c, 0x0d, 0x10, 0x10, 0x0e, 0x0f,
    }
  };
  vector unsigned short *vdata = (vector unsigned short *) in;
  vector float *vout = (vector float *) out;
  vector unsigned int vtmp;
  int i;

  for (i = 0; i < size / 4; i++) {
    vtmp = vec_perm(vdata[i / 2], vzero, vpat[i % 2]);
    vout[i] = vec_ctf(vtmp, 1);
  }
}

#define SIZE    (16)

int main(int argc, char *argv[])
{
  unsigned short in[SIZE] __attribute__((aligned(16))) = {
    1,  2,  3,  4,  5,  6,  7,  8,
    9, 10, 11, 12, 13, 14, 15, 16
  };
  float out[SIZE] __attribute__((aligned(16)));
  int i;

  calc_half(SIZE, in, out);

  for (i = 0; i < SIZE; i++) {
    printf("out[%02d]=%0.1f\n", i, out[i]);
  }

  return 0;
}
こいつはちょっと自信作。だいぶすっきりしたと思う。

演習問題 (2-3)は、もともとそれなりにすっきりしていたのでリファクタリングなし。

演習問題 (2-4)
#include <stdio.h>
#include <altivec.h>

/**
 * グレースケール変換
 * @param src 変換元データ(16バイトアライン)
 * @param dst 変換後データ(16バイトアライン)
 * @param num データ数(4の倍数)
 */
void rgb2y(unsigned char *src, unsigned char *dst, int num) {
  static vector float vzero_f;
  static vector unsigned int vzero_i;
  static vector unsigned char vpat_r = (vector unsigned char) {
    0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x04,
    0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x0c,
  };
  static vector unsigned char vpat_g = (vector unsigned char) {
    0x10, 0x10, 0x10, 0x01, 0x10, 0x10, 0x10, 0x05,
    0x10, 0x10, 0x10, 0x09, 0x10, 0x10, 0x10, 0x0d,
  };
  static vector unsigned char vpat_b = (vector unsigned char) {
    0x10, 0x10, 0x10, 0x02, 0x10, 0x10, 0x10, 0x06,
    0x10, 0x10, 0x10, 0x0a, 0x10, 0x10, 0x10, 0x0e,
  };
  static vector unsigned char vpat_y = (vector unsigned char) {
    0x03, 0x03, 0x03, 0x10, 0x07, 0x07, 0x07, 0x10,
    0x0b, 0x0b, 0x0b, 0x10, 0x0f, 0x0f, 0x0f, 0x10,
  };
  static vector float vrc = (vector float) {
    0.29891, 0.29891, 0.29891, 0.29891
  };
  static vector float vgc = (vector float) {
    0.58661, 0.58661, 0.58661, 0.58661
  };
  static vector float vbc = (vector float) {
    0.11448, 0.11448, 0.11448, 0.11448
  };
  vector unsigned int *vsrc = (vector unsigned int *) src;
  vector unsigned char *vdst = (vector unsigned char *) dst;
  vector unsigned int vint;
  vector unsigned int vmax = (vector unsigned int) {255, 255, 255, 255};
  vector unsigned int vpat_max;
  vector float vr, vg, vb, vy;
  int i;

  for (i = 0; i < num / 4; i++) {
    vint = vec_perm(vsrc[i], vzero_i, vpat_r);
    vr = vec_ctf(vint, 0);
    vint = vec_perm(vsrc[i], vzero_i, vpat_g);
    vg = vec_ctf(vint, 0);
    vint = vec_perm(vsrc[i], vzero_i, vpat_b);
    vb = vec_ctf(vint, 0);
    vy = vec_madd(vr, vrc, vzero_f);
    vy = vec_madd(vg, vgc, vy);
    vy = vec_madd(vb, vbc, vy);
    vint = vec_ctu(vy, 0);
    vpat_max = vec_cmpgt(vint, vmax);
    vint = vec_sel(vint, vpat_max, vpat_max);
    vdst[i] = vec_perm(vint, vzero_i, vpat_y);
  }
}
こいつは、コンパイルエラーだけは出ないことを確認したけど、テストプログラムを書いていないのであっているかどうか全然わからない。
テストプログラムは、次のエントリで。

カテゴリ

トラックバック(0)

このブログ記事を参照しているブログ一覧: CELLプログラミングその3

このブログ記事に対するトラックバックURL: https://www.wizard-limit.net/cgi-bin/mt/mt-tb.cgi/1115

コメントする

このブログ記事について

このページは、falseが2007年1月 2日 21:32に書いたブログ記事です。

ひとつ前のブログ記事は「CELLプログラミングその2」です。

次のブログ記事は「CELLプログラミングその4」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

広告

Powered by Movable Type 6.1.1