MUSASHI C source: xtbucket.c


0001:  
0002: /*============================================================================*/ 
0003: /* 変更履歴                                                                   */ 
0004: /*----------------------------------------------------------------------------*/ 
0005: /* 1.0 : 新しいAPIに対応 2003/06/20                                           */ 
0006: /*============================================================================*/ 
0007: #include <musashi.h
0008: #include <stdlib.h> 
0009: #include <string.h> 
0010: #include <float.h> 
0011:  
0012: #include <xtbucketHelp.h> 
0013: struct mssComHelp comHelp={ 
0014:   "xtbucket",     /* コマンド名       */ 
0015:   "1.0",          /* バージョン       */ 
0016:   HELPT,          /* コマンドタイトル */ 
0017:   HELPS,          /* 要約             */ 
0018:   HELPE,          /* 利用例           */ 
0019:   HELPR,          /* 参照コマンド     */ 
0020:   HELPA,          /* 作者情報         */ 
0021:   HELPB,          /* バグレポート情報 */ 
0022:   HELPH           /* ホームページ     */ 
0023: }; 
0024:  
0025: extern struct mssGlobalVariables mssGV; 
0026:  
0027: #define MALLOC_CNT 1000 
0028:  
0029: struct ctbl { /*count table*/ 
0030:   double Val; 
0031:   unsigned long Cnt; 
0032: }; 
0033:  
0034: struct kTbl { /*k-cluster table*/ 
0035:            double minVar; 
0036:   unsigned long prvNo; 
0037:   unsigned long from; 
0038:   unsigned long to; 
0039: }; 
0040:  
0041: struct rTbl { /*range table*/ 
0042:   double from; 
0043:   double to; 
0044: }; 
0045:  
0046: static struct ctbl *cTable;       /*値とその件数の入った配列*/ 
0047: static long         cTableCnt;    /*各cTable配列に登録されている件数*/ 
0048: static long         cTableMaxCnt; /*各cTable配列に登録可能最大件数(malloc)*/ 
0049:  
0050: static struct kTbl   *kTable; 
0051: static struct rTbl   *rTable; 
0052: static unsigned long *sTable; 
0053: static struct rTbl   **rTables; 
0054:  
0055: int cutCnt; /*実際の分割数*/ 
0056:  
0057: void insertValue( 
0058:   double value, /*挿入する値*/ 
0059:   int    start /*挿入するスタート位置*/ 
0060:                  ){ 
0061:   int i; 
0062:  
0063:   /*メモリオーバー時のリアロケーション(MALLOC_CNT行単位で増える) */ 
0064:   if( cTableCnt >= cTableMaxCnt) { 
0065:     cTableMaxCnt+=MALLOC_CNT; 
0066:     cTable = (struct ctbl *)mssRealloc(cTable, 
0067:                              cTableMaxCnt * sizeof(struct ctbl),"xtbucket"); 
0068:   } 
0069:  
0070:   for(i=cTableCnt-1; i>=start; i--){ 
0071:     (cTable+i+1)->Val = (cTable+i)->Val; 
0072:     (cTable+i+1)->Cnt = (cTable+i)->Cnt; 
0073:   } 
0074:   (cTable+start)->Val = value; 
0075:   (cTable+start)->Cnt = 1; 
0076:   cTableCnt++; 
0077: } 
0078:  
0079: void setCntTable(char *str){ 
0080:   /*バイナリサーチで探索するスタート位置とエンド位置とその中間値*/ 
0081:   double value; /*テーブルにセットする値*/ 
0082:   int start; 
0083:   int end; 
0084:   int try=0; 
0085:  
0086:   if(MssIsNull(str))return; 
0087:  
0088:   value=atof(str); 
0089:   /*探索中に同じ値がテーブルに見つかればカウントアップ*/ 
0090:   /*見つからなければstartの位置にその値を挿入する*/ 
0091:   start=0; 
0092:   end=cTableCnt-1; 
0093:   while(start<=end){ 
0094:     try=(start+end)/2; 
0095:     if((cTable+try)->Val > value) { 
0096:       end=try-1; 
0097:     } else if((cTable+try)->Val < value) { 
0098:       start=try+1; 
0099:     } else { 
0100:       (cTable+try)->Cnt++; 
0101:       return; 
0102:     } 
0103:   } 
0104:   /*探索で見つからなければその値をテーブルに新規登録*/ 
0105:   insertValue(value, start); 
0106:   return; 
0107: } 
0108:  
0109:  
0110: /*----------------------------------------------------------------------------*/ 
0111: /*データのメモリへのセット 
0112: cTable[i]にセットされる iはf=で指定した項目番号を0から順番に割り振った番号 
0113:                         ex)f=2,5の場合 cTable[0]が項目2,cTable[1]が項目5 
0114: cTable[i]にmallocで確保された領域の先頭アドレスがセットされる。 
0115: 領域は次の構造体のデータ構造を持つ 
0116: double Val;        値 
0117: unsigned long Cnt; その値の出現件数 
0118: */ 
0119: /*----------------------------------------------------------------------------*/ 
0120: struct ctbl *setcTable(struct mssFldRecKey *frk,int fldNo){ 
0121: /*  int i;*/ 
0122:  
0123:   cTableMaxCnt=MALLOC_CNT; 
0124:   cTable =NULL; 
0125:   cTable =(struct ctbl *)mssCalloc(cTableMaxCnt*sizeof(struct ctbl),"xtbucket"); 
0126:  
0127:   mssSeekTopFRK(frk); 
0128:   while( EOF != mssReadFldRecFRK(frk) ){ 
0129:     /*項目の値をセットする*/ 
0130:     setCntTable(*(frk->pnt+fldNo)); 
0131:   } 
0132:  
0133: /* デバッグリスト*/ 
0134: /* 
0135:   for(i=0; i<cTableCnt; i++){ 
0136:     printf("field[%d] %g - %ld\n",i,(cTable+i)->Val,(cTable+i)->Cnt); 
0137:   } 
0138: */ 
0139:   return(cTable); 
0140: } 
0141:  
0142: /*cTableにおいて、startからendまでの件数二乗和を求める*/ 
0143: /*分散最小化は件数の二乗和最小化に等しいので*/ 
0144: double calVariance( int start, int end){ 
0145:   double result=0; 
0146:   int i; 
0147:   for(i=start; i<=end; i++){ 
0148:     result+=(cTable+i)->Cnt; 
0149:   } 
0150:   return(result*result); 
0151: } 
0152:  
0153: /*----------------------------------------------------------------------------*/ 
0154: /* 最適カットポイントを求める                                                 */ 
0155: /*----------------------------------------------------------------------------*/ 
0156: /* 
0157: Algorithm by N.Katoh 
0158: kTableとは、分散最小化を求めるためのワークテーブルで以下のような構造をとる 
0159: kTableからrTableが作られる。 
0160:  
0161: 分割数 値1    値2    値3    ... 値k 
0162:      1 a(1,1) a(1,2) a(1,3) ... a(1,k) 
0163:      2 a(2,1) a(2,2) a(2,3) ... a(2,k) 
0164:      3 a(3,1) a(3,2) a(3,3) ... a(3,k) 
0165:      .   .      .      .    ...   . 
0166:      .   .      .      .    ...   . 
0167:      j a(j,1) a(j,2) a(j,3) ... a(j,k) 
0168:  
0169: a(j,k)には次の構造体を持つ 
0170:            double minVar; 
0171:   unsigned long prvNo; 
0172:   unsigned long from; 
0173:   unsigned long to; 
0174: minVarは、k個の値についてj分割したときの最小分散値 
0175: ただし、分散値は用いる必要はなく、単に件数の2乗値で代替することができる 
0176: prvNoは、j分割の場合に、最小分散値を持つようなj-1分割時のk。 
0177: from,toは、j分割の場合に、最小分散値を持つようなj番目の分割範囲。 
0178:  
0179: 分割数1の行は、実際にはcTableの件数の2乗和が入っている 
0180: */ 
0181: /*----------------------------------------------------------------------------*/ 
0182: void calOptCutPoint(int cutNum){ 
0183:  
0184:   unsigned long   maxCnt; 
0185:            double minMinVar=0; 
0186:   unsigned long   minPrvNo=0; 
0187:   unsigned long   minFrom=0; 
0188:   unsigned long   minTo=0; 
0189:            double tmpVar; 
0190:   struct kTbl *tmpKtbl; 
0191:   int j,k,l; 
0192:  
0193:   maxCnt=cTableCnt; /* 値の種類数 */ 
0194:   /*kTableメモリアロケーション*/ 
0195:   kTable = (struct kTbl *)mssCalloc
0196:                           maxCnt*cutNum*sizeof(struct kTbl),"calOptCutP"); 
0197:   /*sTableメモリアロケーション*/ 
0198:   sTable = (unsigned long *)mssCalloc
0199:                           maxCnt*sizeof(unsigned long),"calOptCutP"); 
0200:   /*rTableメモリアロケーション*/ 
0201:   rTable = (struct rTbl *)mssCalloc
0202:                           cutNum*sizeof(struct rTbl),"calOptCutP"); 
0203:  
0204:   /*累積値を持っておく*/ 
0205:   *sTable = cTable->Cnt; 
0206:   for(j=1; j<cTableCnt; j++){ 
0207:     *(sTable+j) = *(sTable+j-1) + (cTable+j)->Cnt; 
0208:   } 
0209:  
0210:   /*k=1の場合の計算*/ 
0211:   for(j=0; j<cTableCnt; j++){ 
0212:     (kTable+j)->minVar = calVariance(0,j); 
0213:     (kTable+j)->prvNo  = 0; 
0214:     (kTable+j)->from   = 0; 
0215:     (kTable+j)->to     = j; 
0216:   } 
0217:  
0218:   /*値の種類数よりもカット数(k=の値)が大きければcutCntを調整*/ 
0219:   cutCnt=cutNum; 
0220:   if(cutNum>cTableCnt)cutCnt=cTableCnt; 
0221:  
0222:   /*k=2以上の場合の計算*/ 
0223:   for(j=1; j<cutCnt; j++){ /*j=1で始まるのはk分割の1は配列の0に対応*/ 
0224:     for(k=j; k<cTableCnt; k++){ 
0225:       minMinVar=DBL_MAX; 
0226:       for(l=j-1; l<k; l++){ 
0227:         tmpVar = (kTable+cTableCnt*(j-1)+l)->minVar + 
0228:                  (double)(sTable[k]-sTable[l])*(double)(sTable[k]-sTable[l]); 
0229:         /*ここの不等式を>にすれば、同じ件数の場合に後を多くする*/ 
0230:         /*ここの不等式を>=にすれば、同じ件数の場合に前を多くする*/ 
0231:         if( minMinVar > tmpVar ){ 
0232:           minMinVar =tmpVar; 
0233:           minPrvNo  =l; 
0234:           minFrom   =l+1; 
0235:           minTo     =k; 
0236:         } 
0237:       } /*for l*/ 
0238:       (kTable+cTableCnt*j+k)->minVar = minMinVar; 
0239:       (kTable+cTableCnt*j+k)->prvNo  = minPrvNo; 
0240:       (kTable+cTableCnt*j+k)->from   = minFrom; 
0241:       (kTable+cTableCnt*j+k)->to     = minTo; 
0242:     }/*for k*/ 
0243:   } /*for j*/ 
0244:  
0245:   tmpKtbl=kTable+cutCnt*cTableCnt-1; 
0246:   for(j=cutCnt-1; j>=0; j--){ 
0247:     //(rTable+cutNum+j)->from=(cTable+(tmpKtbl->from))->Val; 
0248:     //(rTable+cutNum+j)->to  =(cTable+(tmpKtbl->to  ))->Val; 
0249:     (rTable+j)->from=(cTable+(tmpKtbl->from))->Val; 
0250:     (rTable+j)->to  =(cTable+(tmpKtbl->to  ))->Val; 
0251:     tmpKtbl=kTable+(j-1)*cTableCnt+(tmpKtbl->prvNo); 
0252:   } 
0253:   /*fromとtoの中点をとる*/ 
0254:   if(cutCnt>1) (rTable+0)->to=((rTable+0)->to+(rTable+1)->from)/2; 
0255:   for(j=1; j<cutCnt-1; j++){ 
0256:     (rTable+j)->from=(rTable+j-1)->to; 
0257:     (rTable+j)->to  =((rTable+j)->to+(rTable+j+1)->from)/2; 
0258:   } 
0259:   (rTable+j)->from=(rTable+j-1)->to; 
0260:  
0261: /* デバッグリスト*/ 
0262: /* 
0263:   printf("---- kTable : cnt-----\n"); 
0264:   for(j=0; j<cutCnt; j++){ 
0265:     printf("%02d : ",j); 
0266:     for(k=0; k<cTableCnt; k++){ 
0267:       printf("%g ", (kTable+cTableCnt*j+k)->minVar); 
0268:     } 
0269:     printf("\n"); 
0270:   } 
0271:   printf("---- kTable : from,to-----\n"); 
0272:   for(j=0; j<cutCnt; j++){ 
0273:     printf("%02d : ",j); 
0274:     for(k=0; k<cTableCnt; k++){ 
0275:       printf("(%ld,%ld) ", (kTable+cTableCnt*j+k)->from, 
0276:                            (kTable+cTableCnt*j+k)->to   ); 
0277:     } 
0278:     printf("\n"); 
0279:   } 
0280:   printf("---- kTable : prvNo-----\n"); 
0281:   for(j=0; j<cutCnt; j++){ 
0282:     printf("%02d : ",j); 
0283:     for(k=0; k<cTableCnt; k++){ 
0284:       printf("%ld ", (kTable+cTableCnt*j+k)->prvNo); 
0285:     } 
0286:     printf("\n"); 
0287:   } 
0288:   printf("---- rTable : prvNo-----\n"); 
0289:   for(j=0; j<cutCnt; j++){ 
0290:     printf("%g - %g\n", 
0291:     (rTable+j)->from, (rTable+j)->to); 
0292:     //(rTable+cutNum+j)->from, (rTable+cutNum+j)->to); 
0293:   } 
0294:   printf("=============\n"); 
0295: */ 
0296: } 
0297:  
0298: /* 
0299: =============================================================================== 
0300: Main Function 
0301: =============================================================================== 
0302: */ 
0303: int main(int argc, char *argv[]){ 
0304: /*============================================================================*/ 
0305: /* オプション宣言&定義                                                       */ 
0306: /*============================================================================*/ 
0307: /*----------------------------------------------------------------------------*/ 
0308: /* キー項目                                                                   */ 
0309: /*----------------------------------------------------------------------------*/ 
0310:   MssOptKEY optKEY={ 
0311:     OKEY,   /* オプションタイプ                                             */ 
0312:     "k",    /* キーワード(複数文字は不可)                                   */ 
0313:     0,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0314:     MssFieldMaxCnt, /* 指定可能な最大項目数                                 */ 
0315:     "i",    /* 対象とする入力データのキーワード(GUIで利用)                  */ 
0316:     2,      /* デフォルト(このオプションが指定されなかったときの動作を指定) */ 
0317:             /* 1:全ての行を異るキー値として扱う                             */ 
0318:             /* 2:全ての行を同じキー値として扱う)                            */ 
0319:     KEYT,   /* このオプションのタイトル(Helpで表示)                         */ 
0320:     KEYC    /* このオプションのコメント(Helpで表示)                         */ 
0321:   }; 
0322:  
0323: /*----------------------------------------------------------------------------*/ 
0324: /* 対象項目                                                                   */ 
0325: /*----------------------------------------------------------------------------*/ 
0326:   MssOptFLD optFLD={ 
0327:     OFLD,   /* オプションタイプ                                             */ 
0328:     "f",    /* キーワード(複数文字は不可)                                   */ 
0329:     1,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0330:     MssFieldMaxCnt, /* 指定可能な最大項目数                                 */ 
0331:     "i",    /* 対象とする入力データのキーワード(GUIで利用)                  */ 
0332:     1,      /* 正規表現を許可するかどうか(0:不可,1:可)                      */ 
0333:     1,      /* 新項目名を指定できるかどうか(0:不可,1:可)                    */ 
0334:     NULL,   /* 項目オプション(%以下)で指定可能な文字                        */ 
0335:             /* ex) 指定不可の場合はNULL, "nr": "-f 項目名%rn"の指定可能     */ 
0336:     FLDT,   /* このオプションのタイトル(Helpで表示)                         */ 
0337:     FLDC,   /* このオプションのコメント(Helpで表示)                         */ 
0338:     FLDF    /* フラグについての説明(Helpで表示)複数の場合はカンマで区切る   */ 
0339:   }; 
0340:  
0341: /*----------------------------------------------------------------------------*/ 
0342: /* 分割数                                                                     */ 
0343: /*----------------------------------------------------------------------------*/ 
0344:   MssOptINT optNUM={ 
0345:     OINT,   /* オプションタイプ                                             */ 
0346:     "n",    /* キーワード(複数文字は不可)                                   */ 
0347:     1,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0348:     0,      /* デフォルト(数値として指定)                                   */ 
0349:     2,      /* 最小値                                                       */ 
0350:     255,    /* 最大値                                                       */ 
0351:     NUMT,   /* このオプションのタイトル(Helpで表示)                         */ 
0352:     NUMC    /* このオプションのコメント(Helpで表示)                         */ 
0353:   }; 
0354:  
0355: /*----------------------------------------------------------------------------*/ 
0356: /* 出力書式                                                                   */ 
0357: /*----------------------------------------------------------------------------*/ 
0358:   MssOptSEL optFMT={ 
0359:     OSEL,    /* オプションタイプ                                             */ 
0360:     "F",     /* キーワード(複数文字は不可)                                   */ 
0361:     0,       /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0362:     "0",     /* デフォルト(文字列にて)                                       */ 
0363:     "0,1,2", 
0364:             /* 指定可能な値リスト                                           */ 
0365:     FMTT,   /* このオプションのタイトル(Helpで表示)                         */ 
0366:     FMTC,   /* このオプションのコメント(Helpで表示)                         */ 
0367:     FMTS    /* フラグについての説明(Helpで表示)複数の場合はカンマで区切る   */ 
0368:   }; 
0369:  
0370: /*----------------------------------------------------------------------------*/ 
0371: /* バケット計算方法                                                           */ 
0372: /*----------------------------------------------------------------------------*/ 
0373:   MssOptSEL optTyp={ 
0374:     OSEL,    /* オプションタイプ                                             */ 
0375:     "c",     /* キーワード(複数文字は不可)                                   */ 
0376:     0,       /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0377:     "cnt",   /* デフォルト(文字列にて)                                       */ 
0378:     "cnt,rng", 
0379:             /* 指定可能な値リスト                                           */ 
0380:     TYPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0381:     TYPC,   /* このオプションのコメント(Helpで表示)                         */ 
0382:     TYPS    /* フラグについての説明(Helpで表示)複数の場合はカンマで区切る   */ 
0383:   }; 
0384:  
0385: /*----------------------------------------------------------------------------*/ 
0386: /* 番号逆順フラグ                                                             */ 
0387: /*----------------------------------------------------------------------------*/ 
0388:   MssOptFLG optREV={ 
0389:     OFLG,   /* オプションタイプ                                             */ 
0390:     "r",    /* キーワード(複数文字は不可)                                   */ 
0391:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0392:     REVT,   /* このオプションのタイトル(Helpで表示)                         */ 
0393:     REVC    /* このオプションのコメント(Helpで表示)                         */ 
0394:   }; 
0395:  
0396: /*----------------------------------------------------------------------------*/ 
0397: /* 入力ファイル                                                               */ 
0398: /*----------------------------------------------------------------------------*/ 
0399:   MssOptINF optINF={ 
0400:     OINF,   /* オプションタイプ                                             */ 
0401:     "i",    /* キーワード(複数文字は不可)                                   */ 
0402:     0,      /* 0:オプション, 1:必須                                         */ 
0403:     1,      /* 指定可能の最大ファイル数                                     */ 
0404:     0,      /*1:file not foundのエラーで終了しない 0:する                   */ 
0405:     INFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0406:     INFC    /* このオプションのコメント(Helpで表示)                         */ 
0407:   }; 
0408:  
0409: /*----------------------------------------------------------------------------*/ 
0410: /* 出力ファイル                                                               */ 
0411: /*----------------------------------------------------------------------------*/ 
0412:   MssOptOTF optOTF={ 
0413:     OOTF,   /* オプションタイプ                                             */ 
0414:     "o",    /* キーワード(複数文字は不可)                                   */ 
0415:     0,      /* 0:オプション, 1:必須                                         */ 
0416:     OTFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0417:     OTFC    /* このオプションのコメント(Helpで表示)                         */ 
0418:   }; 
0419:  
0420: /*----------------------------------------------------------------------------*/ 
0421: /* 圧縮出力                                                                   */ 
0422: /*----------------------------------------------------------------------------*/ 
0423:   MssOptFLG optZIP={ 
0424:     OFLG,   /* オプションタイプ                                             */ 
0425:     "z",    /* キーワード(複数文字は不可)                                   */ 
0426:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0427:     ZIPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0428:     ZIPC    /* このオプションのコメント(Helpで表示)                         */ 
0429:   }; 
0430:  
0431: /*----------------------------------------------------------------------------*/ 
0432: /* plain text                                                                 */ 
0433: /*----------------------------------------------------------------------------*/ 
0434:   MssOptFLG optTXT={ 
0435:     OFLG,   /* オプションタイプ                                             */ 
0436:     "t",    /* キーワード(複数文字は不可)                                   */ 
0437:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0438:     TXTT,   /* このオプションのタイトル(Helpで表示)                         */ 
0439:     TXTC    /* このオプションのコメント(Helpで表示)                         */ 
0440:   }; 
0441:  
0442: /*----------------------------------------------------------------------------*/ 
0443: /* ワークファイル用ディレクトリ名                                             */ 
0444: /*----------------------------------------------------------------------------*/ 
0445:   MssOptSTR optTMP={ 
0446:     OSTR,   /* オプションタイプ                                             */ 
0447:     "T",    /* キーワード(複数文字は不可)                                   */ 
0448:     0,      /* 0:オプション, 1:必須                                         */ 
0449:     MssTempDir, /* デフォルト                                               */ 
0450:     1,      /* 文字列の最小長                                               */ 
0451:     MssFileNameMaxLen,  /* 文字列の最大長                                   */ 
0452:     TMPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0453:     TMPC    /* このオプションのコメント(Helpで表示)                         */ 
0454:   }; 
0455:  
0456: /*----------------------------------------------------------------------------*/ 
0457: /* オプションをまとめる                                                       */ 
0458: /*----------------------------------------------------------------------------*/ 
0459:   void *opt[]={&optKEY,&optFLD,&optNUM,&optFMT,&optTyp,&optREV, 
0460:                &optINF,&optOTF,&optZIP,&optTXT,&optTMP,NULL}; 
0461:  
0462: /*============================================================================*/ 
0463: /* 変数宣言&定義                                                             */ 
0464: /*============================================================================*/ 
0465:   struct mssHeader    *hdi;     /* 入力ファイル用<head>タグ格納構造体*/ 
0466:   struct mssHeader    *hdo;     /* 出力ファイル用<head>タグ格納構造体*/ 
0467:   struct mssFPR       *fpr;     /* 入力ファイル構造体                */ 
0468:   struct mssFPW       *fpw;     /* 出力ファイル構造体                */ 
0469:   struct mssFldRecKey *frk=NULL;/* キーバッファ構造体                */ 
0470:   struct mssFields    *sf;      /* ソート項目構造体                  */ 
0471:   int sorted;                   /*ソート済チェック用                 */ 
0472:  
0473:   char *vstr; 
0474:   double val; 
0475:   int num;      /*出力するバケット番号*/ 
0476:   int *cutCnts; /*項目毎の実際のバケット数*/ 
0477:   char  *bufStr; 
0478:   double bufNum; 
0479:   double *max; 
0480:   double *min; 
0481:   double rng; 
0482:   int i,j,k; 
0483:  
0484: /*----------------------------------------------------------------------------*/ 
0485: /* 前処理                                                                     */ 
0486: /*----------------------------------------------------------------------------*/ 
0487:   mssInit(argc,argv,&comHelp);       /* シグナル処理などの初期化              */ 
0488:   mssHelpDoc(opt,&comHelp,argc,argv);/* ヘルプ                                */ 
0489:   mssSetOption(opt,argc,argv);       /* コマンドオプションの設定              */ 
0490:   fpr=mssOpenFPR(optINF.str,4);      /* 入力ファイルオープン                  */ 
0491:   hdi=mssReadHeader(fpr);            /* ヘッダの読み込み                      */ 
0492:   mssSetOptKey(&optKEY, hdi);        /* -k 項目をヘッダー項目に関連づける     */ 
0493:   mssSetOptFld(&optFLD, hdi);        /* -f 項目をヘッダー項目に関連づける     */ 
0494:    
0495:   /*ソート項目の作成*/ 
0496:   sf=mssInitFields(); 
0497:   mssAddFieldsByFields(sf,optKEY.flds); /* -k 項目をソート項目としてセット    */ 
0498:   mssSetFieldsSortPriority(sf);         /* ソート優先順位番号を登録順にふる   */ 
0499:   sorted=mssChkSorted(sf,hdi);          /* ソート済かチェック                 */ 
0500:      
0501: /*mssShowFields(sf);*/ 
0502: /*mssShowOption(opt);*/ 
0503: /*mssShowHeader(hdi);*/ 
0504:  
0505: /*----------------------------------------------------------------------------*/ 
0506: /*出力ヘッダーの作成と出力                                                    */ 
0507: /*----------------------------------------------------------------------------*/ 
0508:   /*出力ヘッダーの初期化(タイトル等のコピー)*/                               
0509:   hdo=mssInitCpyHeader(hdi); 
0510:      
0511:   /*入力ヘッダの全項目を追加*/ 
0512:   mssAddFieldsByFields(hdo->flds,hdi->flds); 
0513:  
0514:   /*新項目名を追加する*/ 
0515:   mssAddFieldsByStrList(hdo->flds,optFLD.newNam,optFLD.cnt);                   
0516:      
0517:   /*ソートする必要があるならばsfのソート情報を反映*/ 
0518:   if(!sorted){ 
0519:     mssSetFieldsSort(hdo->flds,sf); 
0520:   }  
0521:      
0522:   /*標準出力オープン+ヘッダーの出力*/ 
0523:   fpw=mssOpenFPW(optOTF.str,optZIP.set,0);                                     
0524:   mssWriteHeader(hdo, fpw); 
0525:      
0526: /*----------------------------------------------------------------------------*/ 
0527: /*メインルーチン                                                              */ 
0528: /*----------------------------------------------------------------------------*/ 
0529:   /*ソートが必用ならばソートしてソート済みファイルとしてオープン*/             
0530:   if(!sorted){ 
0531:     fpr=mssReopenFPRsort(fpr,4,sf,hdi->flds->cnt,optTMP.str); 
0532:   } 
0533:  
0534:   rTables=mssMalloc(optFLD.flds->cnt*sizeof(struct rTbl *),"xtbucket"); 
0535:   cutCnts=mssMalloc(optFLD.flds->cnt*sizeof(int),"xtbucket"); 
0536:  
0537:   /*FRK構造体の初期化*/ 
0538:   frk=mssInitFRK(hdi->flds->cnt, &optKEY,optTMP.str); 
0539:  
0540:   while(1){ /*loop by key*/ 
0541:     /*データ読み込み*/ 
0542:     if(EOF==mssReadFRK(fpr,frk)) break; 
0543:  
0544:     /*範囲均等化分割(rng)*/ 
0545:     if( strcmp("rng",optTyp.str)==0 ){ 
0546:       max=mssMalloc(optFLD.flds->cnt*sizeof(double),"rng1"); 
0547:       min=mssMalloc(optFLD.flds->cnt*sizeof(double),"rng2"); 
0548:       for(i=0; i<optFLD.flds->cnt; i++){ 
0549:         *(max+i)=-DBL_MAX; 
0550:         *(min+i)= DBL_MAX; 
0551:       } 
0552:  
0553:       mssSeekTopFRK(frk); 
0554:       while( EOF != mssReadFldRecFRK(frk) ){ 
0555:         /*最大値、最小値をセットする*/ 
0556:         for(i=0; i<optFLD.flds->cnt; i++){ 
0557:           bufStr=*(frk->pnt+MssFlds2num(optFLD.flds,i)); 
0558:           if(MssIsNull(bufStr)) continue; 
0559:           bufNum=atof(bufStr); 
0560:           if( *(max+i)<bufNum ) *(max+i)=bufNum; 
0561:           if( *(min+i)>bufNum ) *(min+i)=bufNum; 
0562:         } 
0563:       } 
0564:  
0565:       /*rTableメモリアロケーション*/ 
0566:       for(i=0; i<optFLD.flds->cnt; i++){ 
0567:         if( *(max+i)==DBL_MAX || *(min+i)==-DBL_MAX ){ 
0568:           *(rTables+i)=NULL; 
0569:           *(cutCnts+i)=0; /*カット数のセット*/ 
0570:         }else if( *(max+i) == *(min+i) ){ 
0571:           *(rTables+i) = (struct rTbl *)mssMalloc
0572:                           1*sizeof(struct rTbl),"calOptCutP"); 
0573:           ((*(rTables+i))+0)->from=*(min+i); 
0574:           ((*(rTables+i))+0)->to  =*(max+i); 
0575:           *(cutCnts+i)=1; /*カット数のセット*/ 
0576:         }else{ 
0577:           *(rTables+i) = (struct rTbl *)mssMalloc
0578:                           optNUM.val*sizeof(struct rTbl),"calOptCutP"); 
0579:           rng=( *(max+i) - *(min+i) )/(double)optNUM.val; 
0580:           for(j=0; j<optNUM.val; j++){ 
0581:                                  (*(rTables+i)+j)->from=*(min+i)+rng*j; 
0582:             if(j==optNUM.val-1)  (*(rTables+i)+j)->to  =*(max+i); 
0583:             else                 (*(rTables+i)+j)->to  =*(min+i)+rng*(j+1); 
0584:           } 
0585:           *(cutCnts+i)=optNUM.val; /*カット数のセット*/ 
0586:         } 
0587:       } 
0588:       mssFree(max); 
0589:       mssFree(min); 
0590:  
0591:     /*件数均等化分割(cnt)*/ 
0592:     }else{ 
0593:       for(i=0; i<optFLD.flds->cnt; i++){ 
0594:         /*データをcTableにセット*/ 
0595:         cTableCnt=0; 
0596:         cTableMaxCnt=0; 
0597:         cTable=setcTable(frk,MssFlds2num(optFLD.flds,i)); 
0598:  
0599:         /*最適カットポイントを求める*/ 
0600:         calOptCutPoint(optNUM.val); 
0601:  
0602:         /*カット数のセット*/ 
0603:         *(cutCnts+i)=cutCnt; 
0604:  
0605:         /*rTableの保存*/ 
0606:         *(rTables+i)=rTable; 
0607:  
0608:         /*領域開放*/ 
0609:         mssFree(cTable); 
0610:         mssFree(kTable); 
0611:         mssFree(sTable); 
0612:       } 
0613:     } 
0614:  
0615:     /*出力*/ 
0616:     mssSeekTopFRK(frk); 
0617:     while( EOF != mssReadFldRecFRK(frk) ){ 
0618:       mssGV.inCnt++; 
0619:       mssWriteFld(frk->pnt,frk->fldCnt,"",fpw); 
0620:       mssGV.outCnt++; 
0621:  
0622:       for(i=0; i<optFLD.flds->cnt; i++){ 
0623:         mssWriteDlm(fpw); 
0624:         vstr=*(frk->pnt+MssFlds2num(optFLD.flds,i)); 
0625:         if(MssIsNull(vstr) || *(cutCnts+i) == 0){ 
0626:           mssWriteNull(fpw); 
0627:         }else{ 
0628:           val=atof(vstr); 
0629:           for(k=0; k<*(cutCnts+i)-1; k++){ 
0630:             if( val>=(*(rTables+i)+k)->from && val<(*(rTables+i)+k)->to ){ 
0631:               break; 
0632:             } 
0633:           } 
0634:  
0635:           if(optREV.set)num=*(cutCnts+i)-k-1; 
0636:           else          num=k; 
0637:           if(*optFMT.str=='0'){ 
0638:             mssWriteInt(num+1,fpw); 
0639:           }else if(*optFMT.str=='1'){ 
0640:             mssWriteDbl((*(rTables+i)+k)->from,fpw); 
0641:             mssWriteStr("_",fpw); 
0642:             mssWriteDbl((*(rTables+i)+k)->to  ,fpw); 
0643:           }else{ 
0644:             mssWriteInt(num+1,fpw); 
0645:             mssWriteStr(":",fpw); 
0646:             mssWriteDbl((*(rTables+i)+k)->from,fpw); 
0647:             mssWriteStr("_",fpw); 
0648:             mssWriteDbl((*(rTables+i)+k)->to  ,fpw); 
0649:           } 
0650:         } 
0651:       } 
0652:       mssWriteRet(fpw); 
0653:     } 
0654:     for(i=0; i<optFLD.flds->cnt; i++){ 
0655:       mssFree(*(rTables+i)); 
0656:     } 
0657:   } 
0658:  
0659:   /*領域開放*/ 
0660:   mssFree(rTables); 
0661:   mssFree(cutCnts); 
0662:   mssFreeFRK(frk); 
0663:  
0664: /*----------------------------------------------------------------------------*/ 
0665: /*フッター出力&終了処理                                                       */ 
0666: /*----------------------------------------------------------------------------*/ 
0667: /*printf("allocCnt=%d\n",getAllocCnt());*/ 
0668:   mssWriteFooter(fpw);    /* フッターの出力             */ 
0669:   mssCloseFPR(fpr);       /* 入力ファイルのクローズ     */ 
0670:   mssCloseFPW(fpw);       /* 出力ファイルのクローズ     */ 
0671:   mssFreeFields(sf);      /* ソート項目構造体の領域開放 */ 
0672:   mssFreeHeader(hdi);     /* 入力ヘッダ領域開放         */ 
0673:   mssFreeHeader(hdo);     /* 出力ヘッダ領域開放         */ 
0674:   mssFreeOption(opt);     /* オプション領域開放         */ 
0675:   mssShowEndMsg();        /* 完了メッセージ             */ 
0676:   mssEnd(mssExitSuccess); /* 終了                       */ 
0677:   return(0);              /* to avoid warning message   */ 
0678: }